<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>Threadv</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta property="og:type" content="website">
<meta property="og:title" content="Threadv">
<meta property="og:url" content="http://yoursite.com/page/4/index.html">
<meta property="og:site_name" content="Threadv">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Threadv">
  
    <link rel="alternate" href="/atom.xml" title="Threadv" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link rel="stylesheet" href="/css/style.css">
</head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">Threadv</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="Suche"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main">
  
    <article id="post-mysql/sql_数据库基础" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2019/01/14/mysql/sql_数据库基础/" class="article-date">
  <time datetime="2019-01-14T02:16:28.000Z" itemprop="datePublished">2019-01-14</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2019/01/14/mysql/sql_数据库基础/">数据库-基础</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p># </p>
<h2 id="1-1什么是数据库"><a href="#1-1什么是数据库" class="headerlink" title="1.1什么是数据库"></a>1.1什么是数据库</h2><p>​    数据库：保存数据的仓库。它体现我们电脑中，就是一个文件系统。然后把数据都保存这些特殊的文件中，并且需要使用固定的语言（<strong>SQL语言</strong>）去操作文件中的数据。</p>
<p>技术定义：</p>
<p>​    数据库(Database)是按照<a href="https://baike.baidu.com/item/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84" target="_blank" rel="noopener">数据结构</a>来组织、[<a href="https://baike.baidu.com/item/%E5%AD%98%E5%82%A8" target="_blank" rel="noopener">存储</a>和管理数据的建立在计算机存储设备上的仓库。</p>
<h2 id="1-2数据库介绍"><a href="#1-2数据库介绍" class="headerlink" title="1.2数据库介绍"></a>1.2数据库介绍</h2><p>​    我们开发应用程序的时候，程序中的所有数据，最后都需要保存到专业软件中。这些专业的保存数据的软件我们称为数据库。</p>
<p>我们学习数据库，并不是学习如何去开发一个数据库软件，我们学习的是如何使用数据库以及数据库中的数据记录的操作。而数据库软件是由第三方公司研发。</p>
<h2 id="1-3数据库的分类"><a href="#1-3数据库的分类" class="headerlink" title="1.3数据库的分类"></a>1.3数据库的分类</h2><p>​    关系型、非关系型的数据库</p>
<p>常见的数据库软件：</p>
<p>Oracle：它是Oracle公司的大型关系型数据库，它是收费的。</p>
<p>DB2：IBM公司的数据库，它是收费的。</p>
<p>SqlServer：微软数据库。收费</p>
<p>Sybase：Sybase公司的。 工具PowerDesign 数据库建模工具。</p>
<p>MySql：早期瑞典一个公司发明，后期被sun公司收购，后期被Oracle。</p>
<p>Java开发应用程序主要使用的数据库：</p>
<p>MySQL（5.5）、Oracle、DB2。</p>
<h2 id="1-4什么是关系型数据库"><a href="#1-4什么是关系型数据库" class="headerlink" title="1.4什么是关系型数据库"></a>1.4什么是关系型数据库</h2><p>​    在开发软件的时候，软件中的数据之间必然会有一定的关系存在，需要把这些数据保存在数据库中，同时也要维护数据之间的关系，这时就可以直接使用上述的那些数据库。而上述的所有数据库都属于关系型数据库。</p>
<p>​    描述数据之间的关系，并保存在数据库中，同时学习如果根据这些关系查询数据库中的数据，</p>
<p>关系型数据：设计数据库的时候，需要使用E-R图来描述。实体关系</p>
<p>E-R：实体关系图。</p>
<p>​    实体：可以理解成我们Java程序中的一个对象。在E-R图中使用 矩形(长方形) 表示。</p>
<p>针对一个实体中的属性，我们称为这个实体的数据，在E-R图中使用 椭圆表示。</p>
<p>实体和实体之间的关系：在E-R图中使用菱形表示。</p>
<h1 id="2、mysql在linux-安装篇"><a href="#2、mysql在linux-安装篇" class="headerlink" title="2、mysql在linux-安装篇"></a>2、mysql在linux-安装篇</h1><p>##2.1、vmware中安装linux注意事项</p>
<h3 id="2-1-1、记得关闭防火墙"><a href="#2-1-1、记得关闭防火墙" class="headerlink" title="2.1.1、记得关闭防火墙"></a>2.1.1、记得关闭防火墙</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">service iptables stop</span><br><span class="line">chkconfig iptables off（关闭开机自启：所谓的永久关闭防火墙）</span><br></pre></td></tr></table></figure>
<h3 id="2-1-2、创建统一的管理目录"><a href="#2-1-2、创建统一的管理目录" class="headerlink" title="2.1.2、创建统一的管理目录"></a>2.1.2、创建统一的管理目录</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /exprot/software</span><br><span class="line"></span><br><span class="line">mkdir -p /export/servers</span><br></pre></td></tr></table></figure>
<h3 id="2-1-3软件环境"><a href="#2-1-3软件环境" class="headerlink" title="2.1.3软件环境"></a>2.1.3软件环境</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">VMware、crt、centos6.9</span><br></pre></td></tr></table></figure>
<h3 id="2-1-4安装环境"><a href="#2-1-4安装环境" class="headerlink" title="2.1.4安装环境"></a>2.1.4安装环境</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">1、VMware软件安装</span><br><span class="line"></span><br><span class="line">	2、构建虚拟机</span><br><span class="line"></span><br><span class="line">	3、需要配置Linux（ip,mac地址，hostname，防火墙），就可以通过crt这个客户端连接进行操作</span><br><span class="line"></span><br><span class="line">	4、在linux操作系统进行安装msyql-5.6</span><br><span class="line">	</span><br><span class="line">	说明：因为在linux操作系统中，安装软件的方式主要有3种：1、源码安装（redis）2、rpm安装 		</span><br><span class="line"></span><br><span class="line">3、yum在线安装（安装MySQL为例）---linux联网（）</span><br></pre></td></tr></table></figure>
<h2 id="2-2、centos6-9安装mysql"><a href="#2-2、centos6-9安装mysql" class="headerlink" title="2.2、centos6.9安装mysql"></a>2.2、centos6.9安装mysql</h2><h3 id="2-2-1、检查是否有自带的mysql"><a href="#2-2-1、检查是否有自带的mysql" class="headerlink" title="2.2.1、检查是否有自带的mysql"></a>2.2.1、检查是否有自带的mysql</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@hadoop-01 servers]# rpm -qa |grep mysql </span><br><span class="line">mysql-libs-5.1.73-8.el6_8.x86_64</span><br></pre></td></tr></table></figure>
<h3 id="2-2-2、卸载自带的mysql"><a href="#2-2-2、卸载自带的mysql" class="headerlink" title="2.2.2、卸载自带的mysql"></a>2.2.2、卸载自带的mysql</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@hadoop-01 servers]# rpm -e --nodeps mysql-libs-5.1.73-8.el6_8.x86_64</span><br><span class="line">[root@hadoop-01 servers]#</span><br></pre></td></tr></table></figure>
<h3 id="2-2-3、下载mysql安装包"><a href="#2-2-3、下载mysql安装包" class="headerlink" title="2.2.3、下载mysql安装包"></a>2.2.3、下载mysql安装包</h3><h3 id="2-2-4、上传安装包到linux服务器"><a href="#2-2-4、上传安装包到linux服务器" class="headerlink" title="2.2.4、上传安装包到linux服务器"></a>2.2.4、上传安装包到linux服务器</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">rz 上传文件到指定的目录（yum install lrzsz）</span><br><span class="line">/export/software/mysql</span><br></pre></td></tr></table></figure>
<h3 id="2-2-5、安装"><a href="#2-2-5、安装" class="headerlink" title="2.2.5、安装"></a>2.2.5、安装</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rpm -ivh *.rpm</span><br></pre></td></tr></table></figure>
<h3 id="2-2-6、查看初始化密码"><a href="#2-2-6、查看初始化密码" class="headerlink" title="2.2.6、查看初始化密码"></a>2.2.6、查看初始化密码</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">A RANDOM PASSWORD HAS BEEN SET FOR THE MySQL root USER !</span><br><span class="line">You will find that password in &apos;/root/.mysql_secret&apos;.</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">[root@mysql ~]# cat /root/.mysql_secret</span><br><span class="line"># The random password set for the root user at Wed Aug  8 22:19:00 2018 (local time): xQkcU3kbyuZby1_V</span><br><span class="line"></span><br><span class="line">[root@mysql ~]#</span><br></pre></td></tr></table></figure>
<h3 id="2-2-7、启动mysql并登录"><a href="#2-2-7、启动mysql并登录" class="headerlink" title="2.2.7、启动mysql并登录"></a>2.2.7、启动mysql并登录</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">#启动mysql</span><br><span class="line">service mysql start</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#登录mysql</span><br><span class="line">mysql -uroot -p</span><br><span class="line">(粘贴密码：xQkcU3kbyuZby1_V)</span><br></pre></td></tr></table></figure>
<h3 id="2-2-8、修改密码"><a href="#2-2-8、修改密码" class="headerlink" title="2.2.8、修改密码"></a>2.2.8、修改密码</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">set PASSWORD=PASSWORD(&apos;123456&apos;);</span><br></pre></td></tr></table></figure>
<h3 id="2-2-9、退出mysql客户端"><a href="#2-2-9、退出mysql客户端" class="headerlink" title="2.2.9、退出mysql客户端"></a>2.2.9、退出mysql客户端</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;quit</span><br></pre></td></tr></table></figure>
<h3 id="2-2-10、用新密码进行登录"><a href="#2-2-10、用新密码进行登录" class="headerlink" title="2.2.10、用新密码进行登录"></a>2.2.10、用新密码进行登录</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql -uroot -p</span><br><span class="line">123456（新密码）</span><br></pre></td></tr></table></figure>
<h3 id="2-2-11、远程授权"><a href="#2-2-11、远程授权" class="headerlink" title="2.2.11、远程授权"></a>2.2.11、远程授权</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">grant all privileges on *.* to &apos;root&apos; @&apos;%&apos; identified by &apos;123456&apos;; </span><br><span class="line">flush privileges;</span><br></pre></td></tr></table></figure>
<h3 id="2-2-12、验证远程授权是否成功"><a href="#2-2-12、验证远程授权是否成功" class="headerlink" title="2.2.12、验证远程授权是否成功"></a>2.2.12、验证远程授权是否成功</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">通过windows的mysql客户端工具连接，是否能连接上，能连接上就授权成功，没有连接上，说明没有授权成功！</span><br></pre></td></tr></table></figure>
<h1 id="3、mysql-基础操作篇"><a href="#3、mysql-基础操作篇" class="headerlink" title="3、mysql-基础操作篇"></a>3、mysql-基础操作篇</h1><h2 id="3-1、登录mysql"><a href="#3-1、登录mysql" class="headerlink" title="3.1、登录mysql"></a>3.1、登录mysql</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql -uroot -p</span><br><span class="line">123456</span><br></pre></td></tr></table></figure>
<h2 id="3-2、退出mysql"><a href="#3-2、退出mysql" class="headerlink" title="3.2、退出mysql"></a>3.2、退出mysql</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;quit</span><br></pre></td></tr></table></figure>
<h2 id="3-3、输入查询"><a href="#3-3、输入查询" class="headerlink" title="3.3、输入查询"></a>3.3、输入查询</h2><ul>
<li><p>查看当前mysql的版本号及当前时间</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SELECT VERSION(), CURRENT_DATE;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT VERSION(), CURRENT_DATE;</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| VERSION() | CURRENT_DATE |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| 5.6.25    | 2018-08-08   |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">1 row in set (0.32 sec)</span><br></pre></td></tr></table></figure>
</li>
<li><p>mysql中sql语句不区分大小写</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT VERSION(), CURRENT_DATE;</span><br><span class="line">mysql&gt; select version(), current_date;</span><br><span class="line">mysql&gt; SeLeCt vErSiOn(), current_DATE;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT VERSION(), CURRENT_DATE;</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| VERSION() | CURRENT_DATE |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| 5.6.25    | 2018-08-08   |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select version(), current_date;</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| version() | current_date |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| 5.6.25    | 2018-08-08   |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; SeLeCt vErSiOn(), current_DATE;</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| vErSiOn() | current_DATE |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">| 5.6.25    | 2018-08-08   |</span><br><span class="line">+-----------+--------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt;</span><br></pre></td></tr></table></figure>
</li>
<li><p>可以进行简单的计算（如下所示）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;SELECT SIN(PI()/4), (4+1)*5;</span><br><span class="line"></span><br><span class="line">mysql&gt; SELECT SIN(PI()/4), (4+1)*5;</span><br><span class="line">+--------------------+---------+</span><br><span class="line">| SIN(PI()/4)        | (4+1)*5 |</span><br><span class="line">+--------------------+---------+</span><br><span class="line">| 0.7071067811865475 |      25 |</span><br><span class="line">+--------------------+---------+</span><br><span class="line">1 row in set (0.34 sec)</span><br></pre></td></tr></table></figure>
</li>
<li><p>多条语句比较短，可以写在一行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;SELECT VERSION(); SELECT NOW();</span><br><span class="line"></span><br><span class="line">mysql&gt; SELECT VERSION(); SELECT NOW();</span><br><span class="line">+-----------+</span><br><span class="line">| VERSION() |</span><br><span class="line">+-----------+</span><br><span class="line">| 5.6.25    |</span><br><span class="line">+-----------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">+---------------------+</span><br><span class="line">| NOW()               |</span><br><span class="line">+---------------------+</span><br><span class="line">| 2018-08-08 23:11:11 |</span><br><span class="line">+---------------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br></pre></td></tr></table></figure>
</li>
<li><p>多个字段之间可以用逗号分隔，多行组成一条语句结束以分号结束</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT</span><br><span class="line">-&gt; USER()</span><br><span class="line">-&gt; ,</span><br><span class="line">-&gt; CURRENT_DATE;</span><br><span class="line">+---------------+--------------+</span><br><span class="line">| USER() | CURRENT_DATE |</span><br><span class="line">+---------------+--------------+</span><br><span class="line">| jon@localhost | 2010-08-06 |</span><br><span class="line">+---------------+--------------+</span><br></pre></td></tr></table></figure>
</li>
<li><p>sql语句写了一半，又不想执行可以在语句末尾加上’\c’</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select </span><br><span class="line">    -&gt; user()</span><br><span class="line">    -&gt; \c</span><br><span class="line">mysql&gt;</span><br></pre></td></tr></table></figure>
</li>
</ul>
<p>##3.4、创建和使用数据库</p>
<ul>
<li><p>查看当前有哪些数据库</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;show databases;</span><br><span class="line"></span><br><span class="line">mysql&gt; show databases;</span><br><span class="line">+--------------------+</span><br><span class="line">| Database           |</span><br><span class="line">+--------------------+</span><br><span class="line">| information_schema |</span><br><span class="line">| mysql              |</span><br><span class="line">| performance_schema |</span><br><span class="line">| test               |</span><br><span class="line">+--------------------+</span><br><span class="line">4 rows in set (0.07 sec)</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建数据库</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; CREATE DATABASE menagerie;</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用及切换数据库</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; USE menagerie</span><br><span class="line">Database changed</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="3-5、创建表及使用"><a href="#3-5、创建表及使用" class="headerlink" title="3.5、创建表及使用"></a>3.5、创建表及使用</h2><ul>
<li><p>查看当前数据库有哪些表</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;show tables;</span><br></pre></td></tr></table></figure>
</li>
<li><p>创建一个表</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; CREATE TABLE pet (name VARCHAR(20), owner VARCHAR(20),</span><br><span class="line">    -&gt; species VARCHAR(20), sex CHAR(1), birth DATE, death DATE);</span><br></pre></td></tr></table></figure>
</li>
<li><p>校验创建表语句是否和执行的一致</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt;show create table pet;</span><br><span class="line"></span><br><span class="line">+-------+--------------------------------</span><br><span class="line">| Table | Create Table                   </span><br><span class="line">+-------+--------------------------------</span><br><span class="line">| pet   | CREATE TABLE `pet` (</span><br><span class="line">  `name` varchar(20) DEFAULT NULL,</span><br><span class="line">  `owner` varchar(20) DEFAULT NULL,</span><br><span class="line">  `species` varchar(20) DEFAULT NULL,</span><br><span class="line">  `sex` char(1) DEFAULT NULL,</span><br><span class="line">  `birth` date DEFAULT NULL,</span><br><span class="line">  `death` date DEFAULT NULL</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=latin1 |</span><br><span class="line">+-------+--------------------------------</span><br></pre></td></tr></table></figure>
</li>
<li><p>查看表详情</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; desc pet;</span><br><span class="line">+---------+-------------+------+-----+---------+-------+</span><br><span class="line">| Field   | Type        | Null | Key | Default | Extra |</span><br><span class="line">+---------+-------------+------+-----+---------+-------+</span><br><span class="line">| name    | varchar(20) | YES  |     | NULL    |       |</span><br><span class="line">| owner   | varchar(20) | YES  |     | NULL    |       |</span><br><span class="line">| species | varchar(20) | YES  |     | NULL    |       |</span><br><span class="line">| sex     | char(1)     | YES  |     | NULL    |       |</span><br><span class="line">| birth   | date        | YES  |     | NULL    |       |</span><br><span class="line">| death   | date        | YES  |     | NULL    |       |</span><br><span class="line">+---------+-------------+------+-----+---------+-------+</span><br></pre></td></tr></table></figure>
</li>
<li><p>准备数据</p>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Fluffy Harold cat f 1993-02-04</span><br><span class="line">Claws Gwen cat m 1994-03-17</span><br><span class="line">Buffy Harold dog f 1989-05-13</span><br><span class="line">Fang Benny dog m 1990-08-27</span><br><span class="line">Bowser Diane dog m 1979-08-31 1995-07-29</span><br><span class="line">Chirpy Gwen bird f 1998-09-11</span><br><span class="line">Whistler Gwen bird 1997-12-09</span><br><span class="line">Slim Benny snake m 1996-04-29</span><br></pre></td></tr></table></figure>
<h2 id="3-6、表中导入数据"><a href="#3-6、表中导入数据" class="headerlink" title="3.6、表中导入数据"></a>3.6、表中导入数据</h2><p>​    在表中导入数据的方式有两种</p>
<ul>
<li><p>第一种：将以上数据整理成SQL语句，insert into pet….</p>
</li>
<li><p>第二种：通过加载文件的方式将数据导入到表中</p>
<p>1、创建一个pet.txt的文件（注：每个字段中用tab键隔开，字段没有值得记录用\N代替）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">Fluffy  Harold  cat     f       1993-02-04</span><br><span class="line">Claws   Gwen    cat     m       1994-03-17</span><br><span class="line">Buffy   Harold  dog     f       1989-05-13</span><br><span class="line">Fang    Benny   dog     m       1990-08-27</span><br><span class="line">Bowser  Diane   dog     m       1979-08-31      1995-07-29</span><br><span class="line">Chirpy  Gwen    bird    f       1998-09-11</span><br><span class="line">Whistler        Gwen    bird    \N      1997-12-09      \N</span><br><span class="line">Slim    Benny   snake   m       1996-04-29</span><br></pre></td></tr></table></figure>
<p>2、加载数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; load data local infile &apos;/root/data/pet.txt&apos; into table pet;</span><br><span class="line">Query OK, 8 rows affected, 6 warnings (0.06 sec)</span><br><span class="line">Records: 8  Deleted: 0  Skipped: 0  Warnings: 6</span><br></pre></td></tr></table></figure>
<p>3、校验是否加载进去</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select *from pet;</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| name     | owner  | species | sex  | birth      | death      |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |</span><br><span class="line">| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |</span><br><span class="line">| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |</span><br><span class="line">| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |</span><br><span class="line">| Bowser   | Diane  | dog     | m    | 1979-08-31 | 1995-07-29 |</span><br><span class="line">| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |</span><br><span class="line">| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |</span><br><span class="line">| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">8 rows in set (0.01 sec)</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h2 id="3-7、数据检索部分"><a href="#3-7、数据检索部分" class="headerlink" title="3.7、数据检索部分"></a>3.7、数据检索部分</h2><h3 id="3-7-1、检索全部数据"><a href="#3-7-1、检索全部数据" class="headerlink" title="3.7.1、检索全部数据"></a>3.7.1、检索全部数据</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select *from pet;</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| name     | owner  | species | sex  | birth      | death      |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |</span><br><span class="line">| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |</span><br><span class="line">| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |</span><br><span class="line">| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |</span><br><span class="line">| Bowser   | Diane  | dog     | m    | 1979-08-31 | 1995-07-29 |</span><br><span class="line">| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |</span><br><span class="line">| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |</span><br><span class="line">| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">8 rows in set (0.01 sec)</span><br></pre></td></tr></table></figure>
<h3 id="3-7-2、删除表中全部数据"><a href="#3-7-2、删除表中全部数据" class="headerlink" title="3.7.2、删除表中全部数据"></a>3.7.2、删除表中全部数据</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; DELETE FROM pet;</span><br><span class="line">mysql&gt; LOAD DATA LOCAL INFILE &apos;/path/pet.txt&apos; INTO TABLE pet;</span><br></pre></td></tr></table></figure>
<h3 id="3-7-3、更新表中特定记录的数据"><a href="#3-7-3、更新表中特定记录的数据" class="headerlink" title="3.7.3、更新表中特定记录的数据"></a>3.7.3、更新表中特定记录的数据</h3><ul>
<li>更新表中名字为Bowser的生日</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; UPDATE pet SET birth = &apos;1989-08-31&apos; WHERE name = &apos;Bowser&apos;;</span><br></pre></td></tr></table></figure>
<h3 id="3-7-4、查询特定的行"><a href="#3-7-4、查询特定的行" class="headerlink" title="3.7.4、查询特定的行"></a>3.7.4、查询特定的行</h3><ul>
<li>查询名字为Bowser的记录</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM pet WHERE name = &apos;Bowser&apos;;</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| name | owner | species | sex | birth | death |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br></pre></td></tr></table></figure>
<p>说明：字符串比较不区分大小写！如下所示：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM pet WHERE name = &apos;Bowser&apos;;</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| name   | owner | species | sex  | birth      | death      |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| Bowser | Diane | dog     | m    | 1979-08-31 | 1995-07-29 |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; SELECT * FROM pet WHERE name = &apos;BowsEr&apos;;</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| name   | owner | species | sex  | birth      | death      |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| Bowser | Diane | dog     | m    | 1979-08-31 | 1995-07-29 |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; SELECT * FROM pet WHERE name = &apos;BOWSER&apos;;</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| name   | owner | species | sex  | birth      | death      |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">| Bowser | Diane | dog     | m    | 1979-08-31 | 1995-07-29 |</span><br><span class="line">+--------+-------+---------+------+------------+------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br></pre></td></tr></table></figure>
<h4 id="3-7-4-1、查找生日在1998年以后的特定查询"><a href="#3-7-4-1、查找生日在1998年以后的特定查询" class="headerlink" title="3.7.4.1、查找生日在1998年以后的特定查询"></a>3.7.4.1、查找生日在1998年以后的特定查询</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM pet WHERE birth &gt;= &apos;1998-1-1&apos;;</span><br><span class="line">+----------+-------+---------+------+------------+-------+</span><br><span class="line">| name | owner | species | sex | birth | death |</span><br><span class="line">+----------+-------+---------+------+------------+-------+</span><br><span class="line">| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |</span><br><span class="line">| Puffball | Diane | hamster | f | 1999-03-30 | NULL |</span><br><span class="line">+----------+-------+---------+------+------------+-------+</span><br></pre></td></tr></table></figure>
<h4 id="3-7-4-2、多条件查询（and-or）"><a href="#3-7-4-2、多条件查询（and-or）" class="headerlink" title="3.7.4.2、多条件查询（and | or）"></a>3.7.4.2、多条件查询（and | or）</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM pet WHERE species = &apos;dog&apos; AND sex = &apos;f&apos;;</span><br><span class="line">+-------+--------+---------+------+------------+-------+</span><br><span class="line">| name | owner | species | sex | birth | death |</span><br><span class="line">+-------+--------+---------+------+------------+-------+</span><br><span class="line">| Buffy | Harold | dog | f | 1989-05-13 | NULL |</span><br><span class="line">+-------+--------+---------+------+------------+-------+</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM pet WHERE species = &apos;snake&apos; OR species = &apos;bird&apos;;</span><br><span class="line">+----------+-------+---------+------+------------+-------+</span><br><span class="line">| name | owner | species | sex | birth | death |</span><br><span class="line">+----------+-------+---------+------+------------+-------+</span><br><span class="line">| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |</span><br><span class="line">| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |</span><br><span class="line">| Slim | Benny | snake | m | 1996-04-29 | NULL |</span><br><span class="line">+----------+-------+---------+------+------------+-------+</span><br></pre></td></tr></table></figure>
<ul>
<li><p>优先执行括号中的逻辑</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT * FROM pet WHERE (species = &apos;cat&apos; AND sex = &apos;m&apos;)</span><br><span class="line">-&gt; OR (species = &apos;dog&apos; AND sex = &apos;f&apos;);</span><br><span class="line">+-------+--------+---------+------+------------+-------+</span><br><span class="line">| name | owner | species | sex | birth | death |</span><br><span class="line">+-------+--------+---------+------+------------+-------+</span><br><span class="line">| Claws | Gwen | cat | m | 1994-03-17 | NULL |</span><br><span class="line">| Buffy | Harold | dog | f | 1989-05-13 | NULL |</span><br><span class="line">+-------+--------+---------+------+------------+-------+</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="3-7-5、检索特定的列"><a href="#3-7-5、检索特定的列" class="headerlink" title="3.7.5、检索特定的列"></a>3.7.5、检索特定的列</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, birth FROM pet;</span><br><span class="line">+----------+------------+</span><br><span class="line">| name | birth |</span><br><span class="line">+----------+------------+</span><br><span class="line">| Fluffy | 1993-02-04 |</span><br><span class="line">| Claws | 1994-03-17 |</span><br><span class="line">| Buffy | 1989-05-13 |</span><br><span class="line">| Fang | 1990-08-27 |</span><br><span class="line">| Bowser | 1989-08-31 |</span><br><span class="line">| Chirpy | 1998-09-11 |</span><br><span class="line">| Whistler | 1997-12-09 |</span><br><span class="line">| Slim | 1996-04-29 |</span><br><span class="line">| Puffball | 1999-03-30 |</span><br><span class="line">+----------+------------+</span><br></pre></td></tr></table></figure>
<ul>
<li><p>查询不重复的字段要使用关键词DISTINCT</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT DISTINCT owner FROM pet;</span><br><span class="line">+--------+</span><br><span class="line">| owner |</span><br><span class="line">+--------+</span><br><span class="line">| Benny |</span><br><span class="line">| Diane |</span><br><span class="line">| Gwen |</span><br><span class="line">| Harold |</span><br><span class="line">+--------+</span><br></pre></td></tr></table></figure>
</li>
<li><p>可以使用组合条件查询特定的列</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, species, birth FROM pet</span><br><span class="line">-&gt; WHERE species = &apos;dog&apos; OR species = &apos;cat&apos;;</span><br><span class="line">+--------+---------+------------+</span><br><span class="line">| name | species | birth |</span><br><span class="line">+--------+---------+------------+</span><br><span class="line">| Fluffy | cat | 1993-02-04 |</span><br><span class="line">| Claws | cat | 1994-03-17 |</span><br><span class="line">| Buffy | dog | 1989-05-13 |</span><br><span class="line">| Fang | dog | 1990-08-27 |</span><br><span class="line">| Bowser | dog | 1989-08-31 |</span><br><span class="line">+--------+---------+------------+</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="3-7-6、排序"><a href="#3-7-6、排序" class="headerlink" title="3.7.6、排序"></a>3.7.6、排序</h3><ul>
<li>根据某个字段进行排序（关键词：ORDER BY ）</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, birth FROM pet ORDER BY birth;</span><br><span class="line">+----------+------------+</span><br><span class="line">| name | birth |</span><br><span class="line">+----------+------------+</span><br><span class="line">| Buffy | 1989-05-13 |</span><br><span class="line">| Bowser | 1989-08-31 |</span><br><span class="line">| Fang | 1990-08-27 |</span><br><span class="line">| Fluffy | 1993-02-04 |</span><br><span class="line">| Claws | 1994-03-17 |</span><br><span class="line">| Slim | 1996-04-29 |</span><br><span class="line">| Whistler | 1997-12-09 |</span><br><span class="line">| Chirpy | 1998-09-11 |</span><br><span class="line">| Puffball | 1999-03-30 |</span><br><span class="line">+----------+------------+</span><br></pre></td></tr></table></figure>
<ul>
<li><p>升降序排列（desc：降序；asc：升序）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, birth FROM pet ORDER BY birth desc;//降序排列</span><br><span class="line">mysql&gt; SELECT name, birth FROM pet ORDER BY birth asc ;//升序排列</span><br></pre></td></tr></table></figure>
</li>
<li><p>多列排序</p>
<p>根据species字段升序排列，根据birth字段降序排列</p>
<p><strong>注： ORDER BY species 中无asc，desc，默认为升序排列</strong></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, species, birth FROM pet</span><br><span class="line">-&gt; ORDER BY species, birth DESC;</span><br><span class="line">+----------+---------+------------+</span><br><span class="line">| name | species | birth |</span><br><span class="line">+----------+---------+------------+</span><br><span class="line">| Chirpy | bird | 1998-09-11 |</span><br><span class="line">| Whistler | bird | 1997-12-09 |</span><br><span class="line">| Claws | cat | 1994-03-17 |</span><br><span class="line">| Fluffy | cat | 1993-02-04 |</span><br><span class="line">| Fang | dog | 1990-08-27 |</span><br><span class="line">| Bowser | dog | 1989-08-31 |</span><br><span class="line">| Buffy | dog | 1989-05-13 |</span><br><span class="line">| Puffball | hamster | 1999-03-30 |</span><br><span class="line">| Slim | snake | 1996-04-29 |</span><br><span class="line">+----------+---------+------------+</span><br></pre></td></tr></table></figure>
</li>
</ul>
<h3 id="3-7-7、日期计算"><a href="#3-7-7、日期计算" class="headerlink" title="3.7.7、日期计算"></a>3.7.7、日期计算</h3><p>查看宠物多少岁，就可以使用计算日期的函数TIMESTAMPDIFF()</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">#查询当前的日期</span><br><span class="line">mysql&gt; select curdate() from pet;</span><br><span class="line">+------------+</span><br><span class="line">| curdate()  |</span><br><span class="line">+------------+</span><br><span class="line">| 2018-08-09 |</span><br><span class="line">+------------+</span><br><span class="line"></span><br><span class="line">#获取当年的年</span><br><span class="line">mysql&gt; select YEAR(&apos;2018-02-05&apos;) AS YEARS from pet;</span><br><span class="line">+-------+</span><br><span class="line">| YEARS |</span><br><span class="line">+-------+</span><br><span class="line">|  2018 |</span><br><span class="line">+-------+</span><br><span class="line"></span><br><span class="line">#获取当年的月</span><br><span class="line">mysql&gt; select month(&apos;2018-02-05&apos;) AS YEARS from pet;      </span><br><span class="line">+-------+</span><br><span class="line">| YEARS |</span><br><span class="line">+-------+</span><br><span class="line">|     2 |</span><br><span class="line">+-------+</span><br><span class="line"></span><br><span class="line">#获取当年的日</span><br><span class="line">mysql&gt; select day(&apos;2018-02-05&apos;) AS YEARS from pet;      </span><br><span class="line">+-------+</span><br><span class="line">| YEARS |</span><br><span class="line">+-------+</span><br><span class="line">|     5 |</span><br><span class="line">+-------+</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, birth, CURDATE(),</span><br><span class="line">-&gt; TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age</span><br><span class="line">-&gt; FROM pet;</span><br></pre></td></tr></table></figure>
<h3 id="3-7-8、null和not-null值"><a href="#3-7-8、null和not-null值" class="headerlink" title="3.7.8、null和not null值"></a>3.7.8、null和not null值</h3><p>对一些字段类型要进行检查，判断某些字段是否为NULL，或者 non-NULL</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, birth, death,</span><br><span class="line">-&gt; TIMESTAMPDIFF(YEAR,birth,death) AS age</span><br><span class="line">-&gt; FROM pet WHERE death IS NOT NULL ORDER BY age;</span><br><span class="line">+--------+------------+------------+------+</span><br><span class="line">| name | birth | death | age |</span><br><span class="line">+--------+------------+------------+------+</span><br><span class="line">| Bowser | 1989-08-31 | 1995-07-29 | 5 |</span><br><span class="line">+--------+------------+------------+------+</span><br></pre></td></tr></table></figure>
<h1 id="4、实例"><a href="#4、实例" class="headerlink" title="4、实例"></a>4、实例</h1><p>以下是如何解决MySQL的一些常见问题的示例。</p>
<h2 id="4-1、首先创建一个表，并且导入数据"><a href="#4-1、首先创建一个表，并且导入数据" class="headerlink" title="4.1、首先创建一个表，并且导入数据"></a>4.1、首先创建一个表，并且导入数据</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE shop (</span><br><span class="line">article INT(4) UNSIGNED ZEROFILL DEFAULT &apos;0000&apos; NOT NULL,</span><br><span class="line">dealer CHAR(20) DEFAULT &apos;&apos; NOT NULL,</span><br><span class="line">price DOUBLE(16,2) DEFAULT &apos;0.00&apos; NOT NULL,</span><br><span class="line">PRIMARY KEY(article, dealer));</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">INSERT INTO shop VALUES</span><br><span class="line">(1,&apos;A&apos;,3.45),(1,&apos;B&apos;,3.99),(2,&apos;A&apos;,10.99),(3,&apos;B&apos;,1.45),</span><br><span class="line">(3,&apos;C&apos;,1.69),(3,&apos;D&apos;,1.25),(4,&apos;D&apos;,19.95);</span><br></pre></td></tr></table></figure>
<h2 id="4-2、检索表中的全部数据"><a href="#4-2、检索表中的全部数据" class="headerlink" title="4.2、检索表中的全部数据"></a>4.2、检索表中的全部数据</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">select * from shop;</span><br><span class="line"></span><br><span class="line">+---------+--------+-------+</span><br><span class="line">| article | dealer | price |</span><br><span class="line">+---------+--------+-------+</span><br><span class="line">|    0001 | A      |  3.45 |</span><br><span class="line">|    0001 | B      |  3.99 |</span><br><span class="line">|    0002 | A      | 10.99 |</span><br><span class="line">|    0003 | B      |  1.45 |</span><br><span class="line">|    0003 | C      |  1.69 |</span><br><span class="line">|    0003 | D      |  1.25 |</span><br><span class="line">|    0004 | D      | 19.95 |</span><br><span class="line">+---------+--------+-------+</span><br></pre></td></tr></table></figure>
<h2 id="4-3、求某一列的最大值或者-最小值"><a href="#4-3、求某一列的最大值或者-最小值" class="headerlink" title="4.3、求某一列的最大值或者 最小值"></a>4.3、求某一列的最大值或者 最小值</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">SELECT MAX(article) AS article FROM shop;</span><br><span class="line"></span><br><span class="line">+---------+</span><br><span class="line">| article |</span><br><span class="line">+---------+</span><br><span class="line">|       4 |</span><br><span class="line">+---------+</span><br><span class="line"></span><br><span class="line">//求某一列的最小值</span><br><span class="line"> select min(price) as article from shop; </span><br><span class="line"> </span><br><span class="line"> +---------+</span><br><span class="line">| article |</span><br><span class="line">+---------+</span><br><span class="line">|    1.25 |</span><br><span class="line">+---------+</span><br></pre></td></tr></table></figure>
<p>##4.4、过滤出某个字段值最大的整条记录数据-涉及到子查询</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">SELECT article, dealer, price</span><br><span class="line">FROM shop</span><br><span class="line">WHERE price=(SELECT MAX(price) FROM shop);</span><br><span class="line"></span><br><span class="line">+---------+--------+-------+</span><br><span class="line">| article | dealer | price |</span><br><span class="line">+---------+--------+-------+</span><br><span class="line">|    0004 | D      | 19.95 |</span><br><span class="line">+---------+--------+-------+</span><br></pre></td></tr></table></figure>
<h2 id="4-4、也可以通过关联查询来进行检索"><a href="#4-4、也可以通过关联查询来进行检索" class="headerlink" title="4.4、也可以通过关联查询来进行检索"></a>4.4、也可以通过关联查询来进行检索</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">SELECT s1.article, s1.dealer, s1.price</span><br><span class="line">FROM shop s1</span><br><span class="line">LEFT JOIN shop s2 ON s1.price &lt; s2.price</span><br><span class="line">WHERE s2.article IS NULL;</span><br><span class="line"></span><br><span class="line">SELECT article, dealer, price</span><br><span class="line">FROM shop</span><br><span class="line">ORDER BY price DESC</span><br><span class="line">LIMIT 1;</span><br></pre></td></tr></table></figure>
<h2 id="4-5、求出每一列的最大值，并且根据某一个字段进行分组–分组topn求法"><a href="#4-5、求出每一列的最大值，并且根据某一个字段进行分组–分组topn求法" class="headerlink" title="4.5、求出每一列的最大值，并且根据某一个字段进行分组–分组topn求法"></a>4.5、求出每一列的最大值，并且根据某一个字段进行分组–分组topn求法</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">SELECT article, MAX(price) AS price</span><br><span class="line">FROM shop</span><br><span class="line">GROUP BY article;</span><br><span class="line"></span><br><span class="line">+---------+-------+</span><br><span class="line">| article | price |</span><br><span class="line">+---------+-------+</span><br><span class="line">|    0001 |  3.99 |</span><br><span class="line">|    0002 | 10.99 |</span><br><span class="line">|    0003 |  1.69 |</span><br><span class="line">|    0004 | 19.95 |</span><br><span class="line">+---------+-------+</span><br></pre></td></tr></table></figure>
<p>4.5的另一种写法</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">SELECT article, dealer, price</span><br><span class="line">FROM shop s1</span><br><span class="line">WHERE price=(SELECT MAX(s2.price)</span><br><span class="line">FROM shop s2</span><br><span class="line">WHERE s1.article = s2.article);</span><br><span class="line"></span><br><span class="line">+---------+--------+-------+</span><br><span class="line">| article | dealer | price |</span><br><span class="line">+---------+--------+-------+</span><br><span class="line">|    0001 | B      |  3.99 |</span><br><span class="line">|    0002 | A      | 10.99 |</span><br><span class="line">|    0003 | C      |  1.69 |</span><br><span class="line">|    0004 | D      | 19.95 |</span><br><span class="line">+---------+--------+-------+</span><br></pre></td></tr></table></figure>
<h1 id="5、SQL中的聚合函数"><a href="#5、SQL中的聚合函数" class="headerlink" title="5、SQL中的聚合函数"></a>5、SQL中的聚合函数</h1><p>​    SQL语言中定义了部分的函数，可以帮助我们完成对查询结果的计算操作：</p>
<p>1.count 统计个数（行数）</p>
<p>2.sum函数：求和</p>
<p>3.avg函数：求平均值</p>
<p>4.max、min 求最大值和最小值</p>
<h2 id="5-1、count函数"><a href="#5-1、count函数" class="headerlink" title="5.1、count函数"></a>5.1、count函数</h2><p><strong>语法：select count(*)|count(</strong>列名) from<strong>表名</strong></p>
<p>注意： count在根据指定的列统计的时候，如果这一列中有null 不会被统计在其中。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from pet;</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| name     | owner  | species | sex  | birth      | death      |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| Fluffy   | Harold | cat     | f    | 1993-02-04 | NULL       |</span><br><span class="line">| Claws    | Gwen   | cat     | m    | 1994-03-17 | NULL       |</span><br><span class="line">| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |</span><br><span class="line">| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |</span><br><span class="line">| Bowser   | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |</span><br><span class="line">| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |</span><br><span class="line">| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |</span><br><span class="line">| Slim     | Benny  | snake   | m    | 1996-04-29 | NULL       |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">8 rows in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select count(sex) from pet; </span><br><span class="line">+------------+</span><br><span class="line">| count(sex) |</span><br><span class="line">+------------+</span><br><span class="line">|          7 |</span><br><span class="line">+------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select count(owner) from pet;   </span><br><span class="line">+--------------+</span><br><span class="line">| count(owner) |</span><br><span class="line">+--------------+</span><br><span class="line">|            8 |</span><br><span class="line">+--------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select count(death) from pet;     </span><br><span class="line">+--------------+</span><br><span class="line">| count(death) |</span><br><span class="line">+--------------+</span><br><span class="line">|            1 |</span><br><span class="line">+--------------+</span><br></pre></td></tr></table></figure>
<h2 id="5-2、sum函数"><a href="#5-2、sum函数" class="headerlink" title="5.2、sum函数"></a>5.2、sum函数</h2><p><strong>语法：select sum(</strong>列名) from 表名; </p>
<p>注意事项：</p>
<p>1、如果使用sum 多列进行求和的时候，如果某一列中的有null，这一列所在的行中的其他数据不会被加到总和。</p>
<p>2、可以使用mysql 数据库提供的函数 ifnull(列名,值)</p>
<p>3、在数据库中定义double类型数据，是一个近似值，需要确定准确的位数，这时可以把这一列设计成numeric类型。numeric(数据的总列数,小数位数)</p>
<p>numericdouble float</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select sum(price) from shop;  </span><br><span class="line">+------------+</span><br><span class="line">| sum(price) |</span><br><span class="line">+------------+</span><br><span class="line">|      42.77 |</span><br><span class="line">+------------+</span><br></pre></td></tr></table></figure>
<h2 id="5-3、avg函数"><a href="#5-3、avg函数" class="headerlink" title="5.3、avg函数"></a>5.3、avg函数</h2><p>语法：select avg(列名) from 表名;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select avg(price) from shop;   </span><br><span class="line">+------------+</span><br><span class="line">| avg(price) |</span><br><span class="line">+------------+</span><br><span class="line">|   6.110000 |</span><br><span class="line">+------------+</span><br></pre></td></tr></table></figure>
<h2 id="5-4、max函数"><a href="#5-4、max函数" class="headerlink" title="5.4、max函数"></a>5.4、max函数</h2><p>语法：select max(列名) from 表名;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select max(price) from shop;   </span><br><span class="line">+------------+</span><br><span class="line">| max(price) |</span><br><span class="line">+------------+</span><br><span class="line">|      19.95 |</span><br><span class="line">+------------+</span><br></pre></td></tr></table></figure>
<h2 id="5-5、min函数"><a href="#5-5、min函数" class="headerlink" title="5.5、min函数"></a>5.5、min函数</h2><p>语法：select min(列名) from 表名;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select min(price) from shop;   </span><br><span class="line">+------------+</span><br><span class="line">| min(price) |</span><br><span class="line">+------------+</span><br><span class="line">|       1.25 |</span><br><span class="line">+------------+</span><br></pre></td></tr></table></figure>
<h1 id="6、SQL分类"><a href="#6、SQL分类" class="headerlink" title="6、SQL分类"></a>6、SQL分类</h1><h2 id="6-1、DDL-（数据定义问题）"><a href="#6-1、DDL-（数据定义问题）" class="headerlink" title="6.1、DDL （数据定义问题）"></a>6.1、DDL （数据定义问题）</h2><p>数据定义语言 - Data Definition Language</p>
<p>用来定义数据库的对象，如数据表、视图、索引等</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">创建数据库：create database test;</span><br><span class="line">创建视图：create  view  test;</span><br><span class="line">创建索引：create index test;</span><br><span class="line">创建表：create table test1;</span><br></pre></td></tr></table></figure>
<h2 id="6-2、DML-（数据操纵问题）"><a href="#6-2、DML-（数据操纵问题）" class="headerlink" title="6.2、DML  （数据操纵问题）"></a>6.2、DML  （数据操纵问题）</h2><p>数据处理语言 - Data Manipulation Language</p>
<p>在数据库表中更新，增加和删除记录</p>
<p>如 update， insert， delete</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">update tableName set age=&apos;18&apos; where name=&apos;lisi&apos;</span><br><span class="line"></span><br><span class="line">insert into tableName value(&apos;1&apos;,&apos;2&apos;,&apos;3&apos;);</span><br><span class="line"></span><br><span class="line">drop table tableName //删除表操作</span><br></pre></td></tr></table></figure>
<h2 id="6-3、DCL-（数据控制问题）"><a href="#6-3、DCL-（数据控制问题）" class="headerlink" title="6.3、DCL （数据控制问题）"></a>6.3、DCL （数据控制问题）</h2><p>数据控制语言 – Data Control Language</p>
<p>指用于设置用户权限和控制事务语句</p>
<p>如grant，revoke，if…else，while，begintransaction</p>
<h2 id="6-4、DQL-（数据查询问题）"><a href="#6-4、DQL-（数据查询问题）" class="headerlink" title="6.4、DQL （数据查询问题）"></a>6.4、DQL （数据查询问题）</h2><p>数据查询语言 – Data Query Language</p>
<p>select</p>
<h2 id="6-5、小结"><a href="#6-5、小结" class="headerlink" title="6.5、小结"></a>6.5、小结</h2><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">1、创建数据库：create database  test1;</span><br><span class="line">2、使用数据库：use test1;</span><br><span class="line">3、查看当前数据库中的所有表：show tables ;</span><br><span class="line">4、查看所有的数据库：show databases;</span><br><span class="line"></span><br><span class="line">5、删除数据库：drop database test1;</span><br><span class="line">6、删除数据库中的表：drop table t1;</span><br></pre></td></tr></table></figure>
<h1 id="7、数据库的备份与恢复"><a href="#7、数据库的备份与恢复" class="headerlink" title="7、数据库的备份与恢复"></a>7、数据库的备份与恢复</h1><h2 id="7-1、备份命令"><a href="#7-1、备份命令" class="headerlink" title="7.1、备份命令"></a>7.1、备份命令</h2><p>​    在mysql的安装目录的bin目录下有mysqldump命令，可以完成对数据库的备份。</p>
<p>语法：mysqldump -u 用户名 -p 数据库名&gt; 磁盘SQL文件路径</p>
<p>由于mysqldump命令不是sql命令，需要在dos窗口下使用。</p>
<p>​    注意：在备份数据的时候，数据库不会被删除。可以手动删除数据库。同时在恢复数据的时候，不会</p>
<p>自动的给我们创建数据库，仅仅只会恢复数据库中的表和表中的数据。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">mysqldump -uroot -p123456 menagerie &gt;/root/data/menagerie.sql</span><br><span class="line"></span><br><span class="line">//备份的文件</span><br><span class="line">-rw-r--r--. 1 root root 3118 Oct 20 04:04 menagerie.sql</span><br></pre></td></tr></table></figure>
<h2 id="7-2、恢复命令"><a href="#7-2、恢复命令" class="headerlink" title="7.2、恢复命令"></a>7.2、恢复命令</h2><p>恢复数据库，需要手动的先创建数据库：</p>
<p>create database heima2;</p>
<p>语法：mysql -u 用户名-p 导入库名&lt; 硬盘SQL文件绝对路径</p>
<p>需求：</p>
<p>​    1、创建heima8数据库。</p>
<p>​    2、重新开启一个新的dos窗口。</p>
<p>​    3、将mydb2备份的数据表和表数据 恢复到mydb6中。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">//恢复命令</span><br><span class="line">mysql -uroot -p123456 test1&lt;/root/data/menagerie.sql</span><br><span class="line"></span><br><span class="line">//恢复校验</span><br></pre></td></tr></table></figure>
<h1 id="8、多表查询"><a href="#8、多表查询" class="headerlink" title="8、多表查询"></a>8、多表查询</h1><h2 id="8-1、笛卡尔积介绍"><a href="#8-1、笛卡尔积介绍" class="headerlink" title="8.1、笛卡尔积介绍"></a>8.1、笛卡尔积介绍</h2><p>​    笛卡尔乘积是指在数学中，两个集合X和Y的笛卡尓积（Cartesian product），又称直积，表示为X × Y，第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员</p>
<p>准备数据：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">create table A(</span><br><span class="line">  A_ID int primary key auto_increment,</span><br><span class="line">  A_NAME varchar(20) not null</span><br><span class="line">);</span><br><span class="line">insert into A values(1,&apos;apple&apos;);</span><br><span class="line">insert into A values(2,&apos;orange&apos;);</span><br><span class="line">insert into A values(3,&apos;banana&apos;);</span><br><span class="line"></span><br><span class="line">create table B( </span><br><span class="line">   A_ID int primary key auto_increment,</span><br><span class="line">   B_PRICE double</span><br><span class="line">);</span><br><span class="line">insert into B values(1,2.30);</span><br><span class="line">insert into B values(2,3.50);</span><br><span class="line">insert into B values(4,null);</span><br></pre></td></tr></table></figure>
<p>展示效果：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A,B;</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">| A_ID | A_NAME | A_ID | B_PRICE |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">|    1 | apple  |    1 |     2.3 |</span><br><span class="line">|    2 | orange |    1 |     2.3 |</span><br><span class="line">|    3 | banana |    1 |     2.3 |</span><br><span class="line">|    1 | apple  |    2 |     3.5 |</span><br><span class="line">|    2 | orange |    2 |     3.5 |</span><br><span class="line">|    3 | banana |    2 |     3.5 |</span><br><span class="line">|    1 | apple  |    4 |    NULL |</span><br><span class="line">|    2 | orange |    4 |    NULL |</span><br><span class="line">|    3 | banana |    4 |    NULL |</span><br><span class="line">+------+--------+------+---------+</span><br></pre></td></tr></table></figure>
<p>作用：笛卡尔积的数据，对程序是没有意义的，我们需要对笛卡尔积中的数据再次进行过滤。</p>
<p>对于多表查询操作，需要过滤出满足条件的数据，需要把多个表进行连接，连接之后需要加上过滤的条件。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A,B where B.A_ID=1;</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">| A_ID | A_NAME | A_ID | B_PRICE |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">|    1 | apple  |    1 |     2.3 |</span><br><span class="line">|    2 | orange |    1 |     2.3 |</span><br><span class="line">|    3 | banana |    1 |     2.3 |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">3 rows in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from A,B where B.A_ID=1 and A.A_ID=1;</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">| A_ID | A_NAME | A_ID | B_PRICE |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">|    1 | apple  |    1 |     2.3 |</span><br><span class="line">+------+--------+------+---------+</span><br></pre></td></tr></table></figure>
<h2 id="8-2、内连接"><a href="#8-2、内连接" class="headerlink" title="8.2、内连接"></a>8.2、内连接</h2><p>内连接：<br>语法一：<br>select 列名 , 列名 …. from 表名1,表名2 where 表名1.列名 = 表名2.列名;</p>
<p>语法二：</p>
<p>select * from 表名1  inner join 表名2 on 条件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A inner join B on A.A_ID=B.A_ID;</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">| A_ID | A_NAME | A_ID | B_PRICE |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">|    1 | apple  |    1 |     2.3 |</span><br><span class="line">|    2 | orange |    2 |     3.5 |</span><br><span class="line">+------+--------+------+---------+</span><br></pre></td></tr></table></figure>
<h2 id="8-3、左外连接"><a href="#8-3、左外连接" class="headerlink" title="8.3、左外连接"></a>8.3、左外连接</h2><p>外链接：左外连接、右外连接、全连接、自连接。</p>
<p>左外连接：用左边表去右边表中查询对应记录，不管是否找到，都将显示左边表中全部记录。</p>
<p>即：虽然右表没有香蕉对应的价格，也要把他查询出来。</p>
<p>语法：select * from 表1 left outer join 表2 on 条件;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A left join B on A.A_ID=B.A_ID;</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">| A_ID | A_NAME | A_ID | B_PRICE |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">|    1 | apple  |    1 |     2.3 |</span><br><span class="line">|    2 | orange |    2 |     3.5 |</span><br><span class="line">|    3 | banana | NULL |    NULL |</span><br><span class="line">+------+--------+------+---------+</span><br></pre></td></tr></table></figure>
<h2 id="8-4、右外连接"><a href="#8-4、右外连接" class="headerlink" title="8.4、右外连接"></a>8.4、右外连接</h2><p>用右边表去左边表查询对应记录，不管是否找到，右边表全部记录都将显示。</p>
<p>即：不管左方能够找到右方价格对应的水果，都要把左方的价格显示出来。</p>
<p>语法：select * from 表1 right outer join 表2 on 条件;</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A right join B on A.A_ID=B.A_ID;     </span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">| A_ID | A_NAME | A_ID | B_PRICE |</span><br><span class="line">+------+--------+------+---------+</span><br><span class="line">|    1 | apple  |    1 |     2.3 |</span><br><span class="line">|    2 | orange |    2 |     3.5 |</span><br><span class="line">| NULL | NULL   |    4 |    NULL |</span><br><span class="line">+------+--------+------+---------+</span><br></pre></td></tr></table></figure>
<h2 id="8-5、全外连接"><a href="#8-5、全外连接" class="headerlink" title="8.5、全外连接"></a>8.5、全外连接</h2><p>全外连接：左外连接和右外连接的结果合并，单会去掉重复的记录。<br>select <em> from 表1 full outer join 表2 on 条件<br>select </em> from a full outer join b on a.A_ID = b.A_ID; 但是mysql数据库不支持此语法。</p>
<h2 id="8-6、关联子查询"><a href="#8-6、关联子查询" class="headerlink" title="8.6、关联子查询"></a>8.6、关联子查询</h2><p>子查询：把一个sql的查询结果作为另外一个查询的参数存在。</p>
<h3 id="8-6-1、in和exist关键词的用法"><a href="#8-6-1、in和exist关键词的用法" class="headerlink" title="8.6.1、in和exist关键词的用法"></a>8.6.1、in和exist关键词的用法</h3><p>关联子查询其他的关键字使用：</p>
<p>回忆：age=23 or age=24  等价于 age in (23,24)</p>
<p>in 表示条件应该是在多个列值中。</p>
<p>in：使用在where后面，经常表示是一个列表中的数据，只要被查询的数据在这个列表中存在即可。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A where A_ID in(1,2,3);</span><br><span class="line">+------+--------+</span><br><span class="line">| A_ID | A_NAME |</span><br><span class="line">+------+--------+</span><br><span class="line">|    1 | apple  |</span><br><span class="line">|    2 | orange |</span><br><span class="line">|    3 | banana |</span><br><span class="line">+------+--------+</span><br><span class="line">3 rows in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from A where A_ID =1 or A_ID =2 or A_ID =3;</span><br><span class="line">+------+--------+</span><br><span class="line">| A_ID | A_NAME |</span><br><span class="line">+------+--------+</span><br><span class="line">|    1 | apple  |</span><br><span class="line">|    2 | orange |</span><br><span class="line">|    3 | banana |</span><br><span class="line">+------+--------+</span><br><span class="line">//not in</span><br><span class="line">mysql&gt; select * from A where A_ID not in (1,2,3,4);</span><br><span class="line">Empty set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from A where A_ID not in (3,4);    </span><br><span class="line">+------+--------+</span><br><span class="line">| A_ID | A_NAME |</span><br><span class="line">+------+--------+</span><br><span class="line">|    1 | apple  |</span><br><span class="line">|    2 | orange |</span><br><span class="line">+------+--------+</span><br><span class="line">2 rows in set (0.00 sec)</span><br></pre></td></tr></table></figure>
<p>exists：</p>
<p>exists：表示存在，当子查询的结果存在，就会显示主查询中的所有数据。</p>
<p>使用exists完成：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A where exists(select A_ID from B);</span><br><span class="line">+------+--------+</span><br><span class="line">| A_ID | A_NAME |</span><br><span class="line">+------+--------+</span><br><span class="line">|    1 | apple  |</span><br><span class="line">|    2 | orange |</span><br><span class="line">|    3 | banana |</span><br><span class="line">+------+--------+</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from A where not exists(select A_ID from B);</span><br><span class="line">Empty set (0.00 sec)</span><br></pre></td></tr></table></figure>
<h3 id="8-6-2、union-和union-all使用法"><a href="#8-6-2、union-和union-all使用法" class="headerlink" title="8.6.2、union 和union  all使用法"></a>8.6.2、union 和union  all使用法</h3><p><strong>UNION 语句</strong>：用于将不同表中相同列中查询的数据展示出来；（不包括重复数据）</p>
<p><strong>UNION ALL 语句</strong>：用于将不同表中相同列中查询的数据展示出来；（包括重复数据）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from A  union   select * from B;   </span><br><span class="line">+------+--------+</span><br><span class="line">| A_ID | A_NAME |</span><br><span class="line">+------+--------+</span><br><span class="line">|    1 | apple  |</span><br><span class="line">|    2 | orange |</span><br><span class="line">|    3 | banana |</span><br><span class="line">|    1 | 2.3    |</span><br><span class="line">|    2 | 3.5    |</span><br><span class="line">|    4 | NULL   |</span><br><span class="line">+------+--------+</span><br><span class="line">6 rows in set (0.00 sec)</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from A  union all  select * from B;</span><br><span class="line">+------+--------+</span><br><span class="line">| A_ID | A_NAME |</span><br><span class="line">+------+--------+</span><br><span class="line">|    1 | apple  |</span><br><span class="line">|    2 | orange |</span><br><span class="line">|    3 | banana |</span><br><span class="line">|    1 | 2.3    |</span><br><span class="line">|    2 | 3.5    |</span><br><span class="line">|    4 | NULL   |</span><br><span class="line">+------+--------+</span><br></pre></td></tr></table></figure>
<h3 id="8-6-3、case-when-语句"><a href="#8-6-3、case-when-语句" class="headerlink" title="8.6.3、case when 语句"></a>8.6.3、case when 语句</h3><p>case when 语句语法结构：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">CASE sex  </span><br><span class="line">WHEN &apos;1&apos; THEN &apos;男&apos;  </span><br><span class="line">WHEN &apos;2&apos; THEN &apos;女&apos;  </span><br><span class="line">ELSE &apos;其他&apos; END</span><br></pre></td></tr></table></figure>
<p>准备数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">//创建表</span><br><span class="line">create table employee(</span><br><span class="line">empid                   int  ,                                       </span><br><span class="line">deptid                  int   ,                                      </span><br><span class="line">sex                     varchar(20)  ,                                    </span><br><span class="line">salary                  double </span><br><span class="line">);</span><br><span class="line"></span><br><span class="line">//加载数据</span><br><span class="line">1	10	female	5500.0</span><br><span class="line">2	10	male	4500.0</span><br><span class="line">3	20	female	1900.0</span><br><span class="line">4	20	male	4800.0</span><br><span class="line">5	40	female	6500.0</span><br><span class="line">6	40	female	14500.0</span><br><span class="line">7	40	male	44500.0</span><br><span class="line">8	50	male	6500.0</span><br><span class="line">9	50	male	7500.0</span><br><span class="line"></span><br><span class="line">load data local infile &apos;/root/data/emp.txt&apos; into table employee ;</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">select *,</span><br><span class="line">case </span><br><span class="line">when salary &lt; 5000 then &quot;低等收入&quot; </span><br><span class="line">when salary&gt;= 5000 and salary &lt; 10000 then &quot;中等收入&quot;</span><br><span class="line">when salary &gt; 10000 then &quot;高等收入&quot;  </span><br><span class="line">end  as level,</span><br><span class="line">case sex</span><br><span class="line">when &quot;female&quot; then 1 </span><br><span class="line">when &quot;male&quot; then 0</span><br><span class="line">end as flag </span><br><span class="line">from employee;</span><br></pre></td></tr></table></figure>
<h1 id="9、MySQL-数据类型"><a href="#9、MySQL-数据类型" class="headerlink" title="9、MySQL 数据类型"></a>9、MySQL 数据类型</h1><p>MySQL中定义数据字段的类型对你数据库的优化是非常重要的。</p>
<p>MySQL支持多种类型，大致可以分为三类：数值、日期/时间和字符串(字符)类型。</p>
<h2 id="9-1、数值类型"><a href="#9-1、数值类型" class="headerlink" title="9.1、数值类型"></a>9.1、数值类型</h2><p>MySQL支持所有标准SQL数值数据类型。</p>
<p>这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC)，以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。</p>
<p>关键字INT是INTEGER的同义词，关键字DEC是DECIMAL的同义词。</p>
<p>BIT数据类型保存位字段值，并且支持MyISAM、MEMORY、InnoDB和BDB表。</p>
<p>作为SQL标准的扩展，MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>大小</th>
<th>范围（有符号）</th>
<th>范围（无符号）</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>TINYINT</td>
<td>1 字节</td>
<td>(-128，127)</td>
<td>(0，255)</td>
<td>小整数值</td>
</tr>
<tr>
<td>SMALLINT</td>
<td>2 字节</td>
<td>(-32 768，32 767)</td>
<td>(0，65 535)</td>
<td>大整数值</td>
</tr>
<tr>
<td>MEDIUMINT</td>
<td>3 字节</td>
<td>(-8 388 608，8 388 607)</td>
<td>(0，16 777 215)</td>
<td>大整数值</td>
</tr>
<tr>
<td>INT或INTEGER</td>
<td>4 字节</td>
<td>(-2 147 483 648，2 147 483 647)</td>
<td>(0，4 294 967 295)</td>
<td>大整数值</td>
</tr>
<tr>
<td>BIGINT</td>
<td>8 字节</td>
<td>(-9 233 372 036 854 775 808，9 223 372 036 854 775 807)</td>
<td>(0，18 446 744 073 709 551 615)</td>
<td>极大整数值</td>
</tr>
<tr>
<td>FLOAT</td>
<td>4 字节</td>
<td>(-3.402 823 466 E+38，-1.175 494 351 E-38)，0，(1.175 494 351 E-38，3.402 823 466 351 E+38)</td>
<td>0，(1.175 494 351 E-38，3.402 823 466 E+38)</td>
<td>单精度浮点数值</td>
</tr>
<tr>
<td>DOUBLE</td>
<td>8 字节</td>
<td>(-1.797 693 134 862 315 7 E+308，-2.225 073 858 507 201 4 E-308)，0，(2.225 073 858 507 201 4 E-308，1.797 693 134 862 315 7 E+308)</td>
<td>0，(2.225 073 858 507 201 4 E-308，1.797 693 134 862 315 7 E+308)</td>
<td>双精度浮点数值</td>
</tr>
<tr>
<td>DECIMAL</td>
<td>对DECIMAL(M,D) ，如果M&gt;D，为M+2否则为D+2</td>
<td>依赖于M和D的值</td>
<td>依赖于M和D的值</td>
<td>小数值</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="9-2、日期和时间类型"><a href="#9-2、日期和时间类型" class="headerlink" title="9.2、日期和时间类型"></a>9.2、日期和时间类型</h2><p>表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。</p>
<p>每个时间类型有一个有效值范围和一个”零”值，当指定不合法的MySQL不能表示的值时使用”零”值。</p>
<p>TIMESTAMP类型有专有的自动更新特性，将在后面描述。</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>大小(字节)</th>
<th>范围</th>
<th>格式</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>DATE</td>
<td>3</td>
<td>1000-01-01/9999-12-31</td>
<td>YYYY-MM-DD</td>
<td>日期值</td>
</tr>
<tr>
<td>TIME</td>
<td>3</td>
<td>‘-838:59:59’/‘838:59:59’</td>
<td>HH:MM:SS</td>
<td>时间值或持续时间</td>
</tr>
<tr>
<td>YEAR</td>
<td>1</td>
<td>1901/2155</td>
<td>YYYY</td>
<td>年份值</td>
</tr>
<tr>
<td>DATETIME</td>
<td>8</td>
<td>1000-01-01 00:00:00/9999-12-31 23:59:59</td>
<td>YYYY-MM-DD HH:MM:SS</td>
<td>混合日期和时间值</td>
</tr>
<tr>
<td>TIMESTAMP</td>
<td>4</td>
<td>1970-01-01 00:00:00/2038结束时间是第 <strong>2147483647</strong> 秒，北京时间 <strong>2038-1-19 11:14:07</strong>，格林尼治时间 2038年1月19日 凌晨 03:14:07</td>
<td>YYYYMMDD HHMMSS</td>
<td>混合日期和时间值，时间戳</td>
</tr>
</tbody>
</table>
<hr>
<h2 id="9-3、字符串类型"><a href="#9-3、字符串类型" class="headerlink" title="9.3、字符串类型"></a>9.3、字符串类型</h2><p>字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。</p>
<table>
<thead>
<tr>
<th>类型</th>
<th>大小</th>
<th>用途</th>
</tr>
</thead>
<tbody>
<tr>
<td>CHAR</td>
<td>0-255字节</td>
<td>定长字符串</td>
</tr>
<tr>
<td>VARCHAR</td>
<td>0-65535 字节</td>
<td>变长字符串</td>
</tr>
<tr>
<td>TINYBLOB</td>
<td>0-255字节</td>
<td>不超过 255 个字符的二进制字符串</td>
</tr>
<tr>
<td>TINYTEXT</td>
<td>0-255字节</td>
<td>短文本字符串</td>
</tr>
<tr>
<td>BLOB</td>
<td>0-65 535字节</td>
<td>二进制形式的长文本数据</td>
</tr>
<tr>
<td>TEXT</td>
<td>0-65 535字节</td>
<td>长文本数据</td>
</tr>
<tr>
<td>MEDIUMBLOB</td>
<td>0-16 777 215字节</td>
<td>二进制形式的中等长度文本数据</td>
</tr>
<tr>
<td>MEDIUMTEXT</td>
<td>0-16 777 215字节</td>
<td>中等长度文本数据</td>
</tr>
<tr>
<td>LONGBLOB</td>
<td>0-4 294 967 295字节</td>
<td>二进制形式的极大文本数据</td>
</tr>
<tr>
<td>LONGTEXT</td>
<td>0-4 294 967 295字节</td>
<td>极大文本数据</td>
</tr>
</tbody>
</table>
<p>CHAR 和 VARCHAR 类型类似，但它们保存和检索的方式不同。它们的最大长度和是否尾部空格被保留等方面也不同。在存储或检索过程中不进行大小写转换。</p>
<p>BINARY 和 VARBINARY 类似于 CHAR 和 VARCHAR，不同的是它们包含二进制字符串而不要非二进制字符串。也就是说，它们包含字节字符串而不是字符字符串。这说明它们没有字符集，并且排序和比较基于列值字节的数值值。</p>
<p>BLOB 是一个二进制大对象，可以容纳可变数量的数据。有 4 种 BLOB 类型：TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它们区别在于可容纳存储范围不同。</p>
<p>有 4 种 TEXT 类型：TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。对应的这 4 种 BLOB 类型，可存储的最大长度不同，可根据实际情况选择。</p>
<p>MySQL 5.0 以上的版本：</p>
<p>1、一个汉字占多少长度与编码有关：</p>
<p><strong>UTF－8</strong>：一个汉字＝3个字节</p>
<p><strong>GBK</strong>：一个汉字＝2个字节</p>
<p>2、varchar(n) 表示 n 个字符，无论汉字和英文，Mysql 都能存入 n 个字符，仅是实际字节长度有所区别</p>
<p>3、MySQL 检查长度，可用 SQL 语言来查看：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">select LENGTH(fieldname) from tablename</span><br></pre></td></tr></table></figure>
<p><strong>1、整型</strong></p>
<table>
<thead>
<tr>
<th><strong>MySQL数据类型</strong></th>
<th><strong>含义（有符号）</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>tinyint(m)</td>
<td>1个字节  范围(-128~127)</td>
</tr>
<tr>
<td>smallint(m)</td>
<td>2个字节  范围(-32768~32767)</td>
</tr>
<tr>
<td>mediumint(m)</td>
<td>3个字节  范围(-8388608~8388607)</td>
</tr>
<tr>
<td>int(m)</td>
<td>4个字节  范围(-2147483648~2147483647)</td>
</tr>
<tr>
<td>bigint(m)</td>
<td>8个字节  范围(+-9.22*10的18次方)</td>
</tr>
</tbody>
</table>
<p>取值范围如果加了 unsigned，则最大值翻倍，如 tinyint unsigned 的取值范围为(0~256)。</p>
<p>int(m) 里的 m 是表示 SELECT 查询结果集中的显示宽度，并不影响实际的取值范围，没有影响到显示的宽度，不知道这个 m 有什么用。</p>
<p><strong>2、浮点型(float 和 double)</strong></p>
<table>
<thead>
<tr>
<th><strong>MySQL数据类型</strong></th>
<th><strong>含义</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>float(m,d)</td>
<td>单精度浮点型    8位精度(4字节)     m总个数，d小数位</td>
</tr>
<tr>
<td>double(m,d)</td>
<td>双精度浮点型    16位精度(8字节)    m总个数，d小数位</td>
</tr>
</tbody>
</table>
<p>设一个字段定义为 float(5,3)，如果插入一个数 123.45678,实际数据库里存的是 123.457，但总个数还以实际为准，即 6 位。</p>
<p><strong>3、定点数</strong></p>
<p>浮点型在数据库中存放的是近似值，而定点类型在数据库中存放的是精确值。</p>
<p>decimal(m,d) 参数 m&lt;65 是总个数，d&lt;30 且 d&lt;m 是小数位。</p>
<p><strong>4、字符串(char,varchar,_text)</strong></p>
<table>
<thead>
<tr>
<th><strong>MySQL数据类型</strong></th>
<th><strong>含义</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>char(n)</td>
<td>固定长度，最多255个字符</td>
</tr>
<tr>
<td>varchar(n)</td>
<td>固定长度，最多65535个字符</td>
</tr>
<tr>
<td>tinytext</td>
<td>可变长度，最多255个字符</td>
</tr>
<tr>
<td>text</td>
<td>可变长度，最多65535个字符</td>
</tr>
<tr>
<td>mediumtext</td>
<td>可变长度，最多2的24次方-1个字符</td>
</tr>
<tr>
<td>longtext</td>
<td>可变长度，最多2的32次方-1个字符</td>
</tr>
</tbody>
</table>
<p>char 和 varchar：</p>
<ul>
<li>** 1.char(n) 若存入字符数小于n，则以空格补于其后，查询之时再将空格去掉。所以 char 类型存储的字符串末尾不能有空格，varchar 不限于此。</li>
<li>** 2.char(n) 固定长度，char(4) 不管是存入几个字符，都将占用 4 个字节，varchar 是存入的实际字符数 +1 个字节（n&lt;=255）或2个字节(n&gt;255)，所以 varchar(4),存入 3 个字符将占用 4 个字节。</li>
<li>** 3.char 类型的字符串检索速度要比 varchar 类型的快。</li>
</ul>
<p>varchar 和 text：</p>
<ul>
<li>** 1.varchar 可指定 n，text 不能指定，内部存储 varchar 是存入的实际字符数 +1 个字节（n&lt;=255）或 2 个字节(n&gt;255)，text 是实际字符数 +2 个字节。</li>
<li>** 2.text 类型不能有默认值。</li>
<li>** 3.varchar 可直接创建索引，text 创建索引要指定前多少个字符。varchar 查询速度快于 text, 在都创建索引的情况下，text 的索引似乎不起作用。</li>
</ul>
<p><strong>5.二进制数据(_Blob)</strong></p>
<ul>
<li>** 1._BLOB和_text存储方式不同，_TEXT以文本方式存储，英文存储区分大小写，而_Blob是以二进制方式存储，不分大小写。</li>
<li>** 2._BLOB存储的数据只能整体读出。</li>
<li>** 3._TEXT可以指定字符集，_BLOB不用指定字符集。</li>
</ul>
<p><strong>6.日期时间类型</strong></p>
<table>
<thead>
<tr>
<th><strong>MySQL数据类型</strong></th>
<th><strong>含义</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>date</td>
<td>日期 ‘2008-12-2’</td>
</tr>
<tr>
<td>time</td>
<td>时间 ‘12:25:36’</td>
</tr>
<tr>
<td>datetime</td>
<td>日期时间 ‘2008-12-2 22:06:44’</td>
</tr>
<tr>
<td>timestamp</td>
<td>自动存储记录修改时间</td>
</tr>
</tbody>
</table>
<p>若定义一个字段为timestamp，这个字段里的时间数据会随其他字段修改的时候自动刷新，所以这个数据类型的字段可以存放这条记录最后被修改的时间。</p>
<p><strong>数据类型的属性</strong></p>
<table>
<thead>
<tr>
<th><strong>MySQL关键字</strong></th>
<th><strong>含义</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>NULL</td>
<td>数据列可包含NULL值</td>
</tr>
<tr>
<td>NOT NULL</td>
<td>数据列不允许包含NULL值</td>
</tr>
<tr>
<td>DEFAULT</td>
<td>默认值</td>
</tr>
<tr>
<td>PRIMARY KEY</td>
<td>主键</td>
</tr>
<tr>
<td>AUTO_INCREMENT</td>
<td>自动递增，适用于整数类型</td>
</tr>
<tr>
<td>UNSIGNED</td>
<td>无符号</td>
</tr>
<tr>
<td>CHARACTER SET name</td>
<td>指定一个字符集</td>
</tr>
</tbody>
</table>
<h1 id="10、MySQL-GROUP-BY-语句"><a href="#10、MySQL-GROUP-BY-语句" class="headerlink" title="10、MySQL GROUP BY 语句"></a>10、MySQL GROUP BY 语句</h1><p>GROUP BY 语句根据一个或多个列对结果集进行分组。</p>
<p>在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。</p>
<p>语法结构：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">SELECT column_name, function(column_name)</span><br><span class="line">FROM table_name</span><br><span class="line">WHERE column_name operator value</span><br><span class="line">GROUP BY column_name;</span><br></pre></td></tr></table></figure>
<p>准备数据：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE `employee_tbl` (</span><br><span class="line">  `id` int(11) NOT NULL,</span><br><span class="line">  `name` char(10) NOT NULL DEFAULT &apos;&apos;,</span><br><span class="line">  `date` datetime NOT NULL,</span><br><span class="line">  `singin` tinyint(4) NOT NULL DEFAULT &apos;0&apos; COMMENT &apos;登录次数&apos;,</span><br><span class="line">  PRIMARY KEY (`id`)</span><br><span class="line">) ENGINE=InnoDB DEFAULT CHARSET=utf8;</span><br><span class="line"></span><br><span class="line">-- ----------------------------</span><br><span class="line"></span><br><span class="line">INSERT INTO `employee_tbl` VALUES (&apos;1&apos;, &apos;小明&apos;, &apos;2016-04-22 15:25:33&apos;, &apos;1&apos;), (&apos;2&apos;, &apos;小王&apos;, &apos;2016-04-20 15:25:47&apos;, &apos;3&apos;), (&apos;3&apos;, &apos;小丽&apos;, &apos;2016-04-19 15:26:02&apos;, &apos;2&apos;), (&apos;4&apos;, &apos;小王&apos;, &apos;2016-04-07 15:26:14&apos;, &apos;4&apos;), (&apos;5&apos;, &apos;小明&apos;, &apos;2016-04-11 15:26:40&apos;, &apos;4&apos;), (&apos;6&apos;, &apos;小明&apos;, &apos;2016-04-04 15:26:54&apos;, &apos;2&apos;);</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SELECT name, COUNT(*) FROM   employee_tbl GROUP BY name;</span><br><span class="line">+--------+----------+</span><br><span class="line">| name   | COUNT(*) |</span><br><span class="line">+--------+----------+</span><br><span class="line">| 小丽 |        1 |</span><br><span class="line">| 小明 |        3 |</span><br><span class="line">| 小王 |        2 |</span><br><span class="line">+--------+----------+</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from employee_tbl;</span><br><span class="line">+----+------+---------------------+--------+</span><br><span class="line">| id | name | date                | singin |</span><br><span class="line">+----+------+---------------------+--------+</span><br><span class="line">|  1 | ??   | 2016-04-22 15:25:33 |      1 |</span><br><span class="line">|  2 | ??   | 2016-04-20 15:25:47 |      3 |</span><br><span class="line">|  3 | ??   | 2016-04-19 15:26:02 |      2 |</span><br><span class="line">|  4 | ??   | 2016-04-07 15:26:14 |      4 |</span><br><span class="line">|  5 | ??   | 2016-04-11 15:26:40 |      4 |</span><br><span class="line">|  6 | ??   | 2016-04-04 15:26:54 |      2 |</span><br><span class="line">+----+------+---------------------+--------+</span><br><span class="line"></span><br><span class="line">mysql&gt; select * from employee_tbl group by singin;</span><br><span class="line">+----+------+---------------------+--------+</span><br><span class="line">| id | name | date                | singin |</span><br><span class="line">+----+------+---------------------+--------+</span><br><span class="line">|  1 | ??   | 2016-04-22 15:25:33 |      1 |</span><br><span class="line">|  3 | ??   | 2016-04-19 15:26:02 |      2 |</span><br><span class="line">|  2 | ??   | 2016-04-20 15:25:47 |      3 |</span><br><span class="line">|  4 | ??   | 2016-04-07 15:26:14 |      4 |</span><br><span class="line">+----+------+---------------------+--------+</span><br></pre></td></tr></table></figure>
<p>注意：</p>
<p>1、group by 可以实现一个最简单的去重查询，假设想看下有哪些员工，除了用 distinct,还可以用：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SELECT name FROM employee_tbl GROUP BY name;</span><br></pre></td></tr></table></figure>
<p>返回的结果集就是所有员工的名字。</p>
<p>2、分组后的条件使用 HAVING 来限定，WHERE 是对原始数据进行条件限制。几个关键字的使用顺序为 where 、group by 、having、order by ，例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">SELECT name ,sum(*)  FROM employee_tbl WHERE id&lt;&gt;1 GROUP BY name  HAVING sum(*)&gt;5 ORDER BY sum(*) DESC;</span><br></pre></td></tr></table></figure>
<h1 id="11、MySQL-LIKE-子句"><a href="#11、MySQL-LIKE-子句" class="headerlink" title="11、MySQL LIKE 子句"></a>11、MySQL LIKE 子句</h1><p>我们知道在 MySQL 中使用 SQL SELECT 命令来读取数据， 同时我们可以在 SELECT 语句中使用 WHERE 子句来获取指定的记录。</p>
<p>WHERE 子句中可以使用等号 = 来设定获取数据的条件，如 “company = ‘test1”。</p>
<p>但是有时候我们需要获取 company 字段含有 “it” 字符的所有记录，这时我们就需要在 WHERE 子句中使用 SQL LIKE 子句。</p>
<p>SQL LIKE 子句中使用百分号 %字符来表示任意字符，类似于UNIX或正则表达式中的星号 *。</p>
<p>如果没有使用百分号 %, LIKE 子句与等号 = 的效果是一样的。</p>
<p>语法：</p>
<p>以下是 SQL SELECT 语句使用 LIKE 子句从数据表中读取数据的通用语法：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">SELECT field1, field2,...fieldN </span><br><span class="line">FROM table_name</span><br><span class="line">WHERE field1 LIKE condition1 [AND [OR]] filed2 = &apos;somevalue&apos;</span><br></pre></td></tr></table></figure>
<ul>
<li>你可以在 WHERE 子句中指定任何条件。</li>
<li>你可以在 WHERE 子句中使用LIKE子句。</li>
<li>你可以使用LIKE子句代替等号 =。</li>
<li>LIKE 通常与 % 一同使用，类似于一个元字符的搜索。</li>
<li>你可以使用 AND 或者 OR 指定一个或多个条件。</li>
<li>你可以在 DELETE 或 UPDATE 命令中使用 WHERE…LIKE 子句来指定条件。</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; select * from pet where species like &apos;%d%&apos;;</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| name     | owner  | species | sex  | birth      | death      |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br><span class="line">| Buffy    | Harold | dog     | f    | 1989-05-13 | NULL       |</span><br><span class="line">| Fang     | Benny  | dog     | m    | 1990-08-27 | NULL       |</span><br><span class="line">| Bowser   | Diane  | dog     | m    | 1989-08-31 | 1995-07-29 |</span><br><span class="line">| Chirpy   | Gwen   | bird    | f    | 1998-09-11 | NULL       |</span><br><span class="line">| Whistler | Gwen   | bird    | NULL | 1997-12-09 | NULL       |</span><br><span class="line">+----------+--------+---------+------+------------+------------+</span><br></pre></td></tr></table></figure>
<h1 id="12、MySQL-NULL-值处理"><a href="#12、MySQL-NULL-值处理" class="headerlink" title="12、MySQL NULL 值处理"></a>12、MySQL NULL 值处理</h1><p>我们已经知道 MySQL 使用 SQL SELECT 命令及 WHERE 子句来读取数据表中的数据,但是当提供的查询条件字段为 NULL 时，该命令可能就无法正常工作。</p>
<p>为了处理这种情况，MySQL提供了三大运算符:</p>
<ul>
<li><strong>IS NULL:</strong> 当列的值是 NULL,此运算符返回 true。</li>
<li><strong>IS NOT NULL:</strong> 当列的值不为 NULL, 运算符返回 true。</li>
<li><strong>&lt;=&gt;:</strong> 比较操作符（不同于=运算符），当比较的的两个值为 NULL 时返回 true。</li>
</ul>
<p>关于 NULL 的条件比较运算是比较特殊的。你不能使用 = NULL 或 != NULL 在列中查找 NULL 值 。</p>
<p>在 MySQL 中，NULL 值与任何其它值的比较（即使是 NULL）永远返回 false，即 NULL = NULL 返回false 。</p>
<p>MySQL 中处理 NULL 使用 IS NULL 和 IS NOT NULL 运算符。</p>
<h1 id="13、MySQL-元数据"><a href="#13、MySQL-元数据" class="headerlink" title="13、MySQL 元数据"></a>13、MySQL 元数据</h1><p>你可能想知道MySQL以下三种信息：</p>
<ul>
<li><strong>查询结果信息：</strong> SELECT, UPDATE 或 DELETE语句影响的记录数。</li>
<li><strong>数据库和数据表的信息：</strong> 包含了数据库及数据表的结构信息。</li>
<li><strong>MySQL服务器信息：</strong> 包含了数据库服务器的当前状态，版本号等。</li>
</ul>
<p>在MySQL的命令提示符中，我们可以很容易的获取以上服务器信息。</p>
<h2 id="获取服务器元数据"><a href="#获取服务器元数据" class="headerlink" title="获取服务器元数据"></a>获取服务器元数据</h2><p>以下命令语句可以在 MySQL 的命令提示符使用，也可以在脚本中 使用，如PHP脚本。</p>
<table>
<thead>
<tr>
<th>命令</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>SELECT VERSION( )</td>
<td>服务器版本信息</td>
</tr>
<tr>
<td>SELECT DATABASE( )</td>
<td>当前数据库名 (或者返回空)</td>
</tr>
<tr>
<td>SELECT USER( )</td>
<td>当前用户名</td>
</tr>
<tr>
<td>SHOW STATUS</td>
<td>服务器状态</td>
</tr>
<tr>
<td>SHOW VARIABLES</td>
<td>服务器配置变量</td>
</tr>
</tbody>
</table>
<h1 id="14、MySQL-ALTER命令"><a href="#14、MySQL-ALTER命令" class="headerlink" title="14、MySQL ALTER命令"></a>14、MySQL ALTER命令</h1><p>当我们需要修改数据表名或者修改数据表字段时，就需要使用到MySQL ALTER命令。</p>
<h2 id="14-1、删除、添加或修改表字段"><a href="#14-1、删除、添加或修改表字段" class="headerlink" title="14.1、删除、添加或修改表字段"></a>14.1、删除、添加或修改表字段</h2><p>如下命令使用了 ALTER 命令及 DROP 子句来删除以上创建表的 i 字段：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl  DROP i;</span><br></pre></td></tr></table></figure>
<p>如果数据表中只剩余一个字段则无法使用DROP来删除字段。</p>
<p>MySQL 中使用 ADD 子句来向数据表中添加列，如下实例在表 testalter_tbl 中添加 i 字段，并定义数据类型:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl ADD i INT;</span><br></pre></td></tr></table></figure>
<p>执行以上命令后，i 字段会自动添加到数据表字段的末尾</p>
<h2 id="14-2、修改字段类型及名称"><a href="#14-2、修改字段类型及名称" class="headerlink" title="14.2、修改字段类型及名称"></a>14.2、修改字段类型及名称</h2><p>如果需要修改字段类型及名称, 你可以在ALTER命令中使用 MODIFY 或 CHANGE 子句 。</p>
<p>例如，把字段 c 的类型从 CHAR(1) 改为 CHAR(10)，可以执行以下命令:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl MODIFY c CHAR(10);</span><br></pre></td></tr></table></figure>
<h2 id="14-3、修改表名"><a href="#14-3、修改表名" class="headerlink" title="14.3、修改表名"></a>14.3、修改表名</h2><p>如果需要修改数据表的名称，可以在 ALTER TABLE 语句中使用 RENAME 子句来实现。</p>
<p>尝试以下实例将数据表 testalter_tbl 重命名为 alter_tbl：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl RENAME TO alter_tbl;</span><br></pre></td></tr></table></figure>
<h1 id="15、MySQL-函数"><a href="#15、MySQL-函数" class="headerlink" title="15、MySQL 函数"></a>15、MySQL 函数</h1><p>MySQL 有很多内置的函数，以下列出了这些函数的说明。</p>
<h2 id="15-1、MySQL-字符串函数"><a href="#15-1、MySQL-字符串函数" class="headerlink" title="15.1、MySQL 字符串函数"></a>15.1、MySQL 字符串函数</h2><table>
<thead>
<tr>
<th>函数</th>
<th>描述</th>
<th>实例</th>
</tr>
</thead>
<tbody>
<tr>
<td>ASCII(s)</td>
<td>返回字符串 s 的第一个字符的 ASCII 码。</td>
<td>返回 CustomerName 字段第一个字母的 ASCII 码：<code>SELECT ASCII(CustomerName) AS NumCodeOfFirstCharFROM Customers;</code></td>
</tr>
<tr>
<td>CHAR_LENGTH(s)</td>
<td>返回字符串 s 的字符数</td>
<td>返回字符串 test1 的字符数<code>SELECT CHAR_LENGTH(&quot;test1&quot;) AS LengthOfString;</code></td>
</tr>
<tr>
<td>CHARACTER_LENGTH(s)</td>
<td>返回字符串 s 的字符数</td>
<td>返回字符串 test1 的字符数<code>SELECT CHARACTER_LENGTH(&quot;test1&quot;) AS LengthOfString;</code></td>
</tr>
<tr>
<td>CONCAT(s1,s2…sn)</td>
<td>字符串 s1,s2 等多个字符串合并为一个字符串</td>
<td>合并多个字符串<code>SELECT CONCAT(&quot;SQL &quot;, &quot;test1 &quot;, &quot;Gooogle &quot;, &quot;Facebook&quot;) AS ConcatenatedString;</code></td>
</tr>
<tr>
<td>CONCAT_WS(x, s1,s2…sn)</td>
<td>同 CONCAT(s1,s2,…) 函数，但是每个字符串直接要加上 x，x 可以是分隔符</td>
<td>合并多个字符串，并添加分隔符：<code>SELECT CONCAT_WS(&quot;-&quot;, &quot;SQL&quot;, &quot;Tutorial&quot;, &quot;is&quot;, &quot;fun!&quot;)AS ConcatenatedString;</code></td>
</tr>
<tr>
<td>FIELD(s,s1,s2…)</td>
<td>返回第一个字符串 s 在字符串列表(s1,s2…)中的位置</td>
<td>返回字符串 c 在列表值中的位置：<code>SELECT FIELD(&quot;c&quot;, &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;);</code></td>
</tr>
<tr>
<td>FIND_IN_SET(s1,s2)</td>
<td>返回在字符串s2中与s1匹配的字符串的位置</td>
<td>返回字符串 c 在指定字符串中的位置：<code>SELECT FIND_IN_SET(&quot;c&quot;, &quot;a,b,c,d,e&quot;);</code></td>
</tr>
<tr>
<td>FORMAT(x,n)</td>
<td>函数可以将数字 x 进行格式化 “#,### .##”, 将 x 保留到小数点后 n 位，最后一位四舍五入。</td>
<td>格式化数字 “#,### .##” 形式：<code>SELECT FORMAT(250500.5634, 2);     -- 输出 250,500.56</code></td>
</tr>
<tr>
<td>INSERT(s1,x,len,s2)</td>
<td>字符串 s2 替换 s1 的 x 位置开始长度为 len 的字符串</td>
<td>从字符串第一个位置开始的 6 个字符替换为 test1：<code>SELECT INSERT(&quot;google.com&quot;, 1, 6, &quot;runnob&quot;);  -- 输出：test1.com</code></td>
</tr>
<tr>
<td>LOCATE(s1,s)</td>
<td>从字符串 s 中获取 s1 的开始位置</td>
<td>获取 b 在字符串 abc 中的位置：<code>SELECT INSTR(&#39;abc&#39;,&#39;b&#39;) -- 2</code></td>
</tr>
<tr>
<td>LCASE(s)</td>
<td>将字符串 s 的所有字母变成小写字母</td>
<td>字符串 test1 转换为小写：<code>SELECT LOWER(&#39;test1&#39;) -- test1</code></td>
</tr>
<tr>
<td>LEFT(s,n)</td>
<td>返回字符串 s 的前 n 个字符</td>
<td>返回字符串 test1 中的前两个字符：<code>SELECT LEFT(&#39;test1&#39;,2) -- it</code></td>
</tr>
<tr>
<td>LEFT(s,n)</td>
<td>返回字符串 s 的前 n 个字符</td>
<td>返回字符串 abcde 的前两个字符：<code>SELECT LEFT(&#39;abcde&#39;,2) -- ab</code></td>
</tr>
<tr>
<td>LOCATE(s1,s)</td>
<td>从字符串 s 中获取 s1 的开始位置</td>
<td>返回字符串 abc 中 b 的位置：<code>SELECT LOCATE(&#39;b&#39;, &#39;abc&#39;) -- 2</code></td>
</tr>
<tr>
<td>LOWER(s)</td>
<td>将字符串 s 的所有字母变成小写字母</td>
<td>字符串 test1 转换为小写：<code>SELECT LOWER(&#39;test1&#39;) -- test1</code></td>
</tr>
<tr>
<td>LPAD(s1,len,s2)</td>
<td>在字符串 s1 的开始处填充字符串 s2，使字符串长度达到 len</td>
<td>将字符串 xx 填充到 abc 字符串的开始处：<code>SELECT LPAD(&#39;abc&#39;,5,&#39;xx&#39;) -- xxabc</code></td>
</tr>
<tr>
<td>LTRIM(s)</td>
<td>去掉字符串 s 开始处的空格</td>
<td>去掉字符串 test1开始处的空格：<code>SELECT LTRIM(&quot;    test1&quot;) AS LeftTrimmedString;-- test1</code></td>
</tr>
<tr>
<td>MID(s,n,len)</td>
<td>从字符串 s 的 start 位置截取长度为 length 的子字符串，同 SUBSTRING(s,n,len)</td>
<td>从字符串 test1 中的第 2 个位置截取 3个 字符：<code>SELECT MID(&quot;test1&quot;, 2, 3) AS ExtractString; -- UNO</code></td>
</tr>
<tr>
<td>POSITION(s1 IN s)</td>
<td>从字符串 s 中获取 s1 的开始位置</td>
<td>返回字符串 abc 中 b 的位置：<code>SELECT POSITION(&#39;b&#39; in &#39;abc&#39;) -- 2</code></td>
</tr>
<tr>
<td>REPEAT(s,n)</td>
<td>将字符串 s 重复 n 次</td>
<td>将字符串 test1 重复三次：<code>SELECT REPEAT(&#39;test1&#39;,3) -- test1test1test1</code></td>
</tr>
<tr>
<td>REPLACE(s,s1,s2)</td>
<td>将字符串 s2 替代字符串 s 中的字符串 s1</td>
<td>将字符串 abc 中的字符 a 替换为字符 x：<code>SELECT REPLACE(&#39;abc&#39;,&#39;a&#39;,&#39;x&#39;) --xbc</code></td>
</tr>
<tr>
<td>REVERSE(s)</td>
<td>将字符串s的顺序反过来</td>
<td>将字符串 abc 的顺序反过来：<code>SELECT REVERSE(&#39;abc&#39;) -- cba</code></td>
</tr>
<tr>
<td>RIGHT(s,n)</td>
<td>返回字符串 s 的后 n 个字符</td>
<td>返回字符串 test1 的后两个字符：<code>SELECT RIGHT(&#39;test1&#39;,2) -- ob</code></td>
</tr>
<tr>
<td>RPAD(s1,len,s2)</td>
<td>在字符串 s1 的结尾处添加字符串 s1，使字符串的长度达到 len</td>
<td>将字符串 xx 填充到 abc 字符串的结尾处：<code>SELECT RPAD(&#39;abc&#39;,5,&#39;xx&#39;) -- abcxx</code></td>
</tr>
<tr>
<td>RTRIM(s)</td>
<td>去掉字符串 s 结尾处的空格</td>
<td>去掉字符串 test1 的末尾空格：<code>SELECT RTRIM(&quot;test1     &quot;) AS RightTrimmedString;   -- test1</code></td>
</tr>
<tr>
<td>SPACE(n)</td>
<td>返回 n 个空格</td>
<td>返回 10 个空格：<code>SELECT SPACE(10);</code></td>
</tr>
<tr>
<td>STRCMP(s1,s2)</td>
<td>比较字符串 s1 和 s2，如果 s1 与 s2 相等返回 0 ，如果 s1&gt;s2 返回 1，如果 s1&lt;s2 返回 -1</td>
<td>比较字符串：<code>SELECT STRCMP(&quot;test1&quot;, &quot;test1&quot;);  -- 0</code></td>
</tr>
<tr>
<td>SUBSTR(s, start, length)</td>
<td>从字符串 s 的 start 位置截取长度为 length 的子字符串</td>
<td>从字符串 test1 中的第 2 个位置截取 3个 字符：<code>SELECT SUBSTR(&quot;test1&quot;, 2, 3) AS ExtractString; -- UNO</code></td>
</tr>
<tr>
<td>SUBSTRING(s, start, length)</td>
<td>从字符串 s 的 start 位置截取长度为 length 的子字符串</td>
<td>从字符串 test1 中的第 2 个位置截取 3个 字符：<code>SELECT SUBSTRING(&quot;test1&quot;, 2, 3) AS ExtractString; -- UNO</code></td>
</tr>
<tr>
<td>SUBSTRING_INDEX(s, delimiter, number)</td>
<td>返回从字符串 s 的第 number 个出现的分隔符 delimiter 之后的子串。如果 number 是正数，返回第 number 个字符左边的字符串。如果 number 是负数，返回第(number 的绝对值(从右边数))个字符右边的字符串。</td>
<td><code>SELECT SUBSTRING_INDEX(&#39;a*b&#39;,&#39;*&#39;,1) -- aSELECT SUBSTRING_INDEX(&#39;a*b&#39;,&#39;*&#39;,-1)    -- bSELECT SUBSTRING_INDEX(SUBSTRING_INDEX(&#39;a*b*c*d*e&#39;,&#39;*&#39;,3),&#39;*&#39;,-1)    -- c</code></td>
</tr>
<tr>
<td>TRIM(s)</td>
<td>去掉字符串 s 开始和结尾处的空格</td>
<td>去掉字符串 test1 的首尾空格：<code>SELECT TRIM(&#39;    test1    &#39;) AS TrimmedString;</code></td>
</tr>
<tr>
<td>UCASE(s)</td>
<td>将字符串转换为大写</td>
<td>将字符串 test1 转换为大写：<code>SELECT UCASE(&quot;test1&quot;); -- test1</code></td>
</tr>
<tr>
<td>UPPER(s)</td>
<td>将字符串转换为大写</td>
<td>将字符串 test1 转换为大写：<code>SELECT UPPER(&quot;test1&quot;); -- test1</code></td>
</tr>
</tbody>
</table>
<hr>
<h2 id="15-2、MySQL-数字函数"><a href="#15-2、MySQL-数字函数" class="headerlink" title="15.2、MySQL 数字函数"></a>15.2、MySQL 数字函数</h2><table>
<thead>
<tr>
<th>函数名</th>
<th>描述</th>
<th>实例</th>
</tr>
</thead>
<tbody>
<tr>
<td>ABS(x)</td>
<td>返回 x 的绝对值</td>
<td>返回 -1 的绝对值：<code>SELECT ABS(-1) -- 返回1</code></td>
</tr>
<tr>
<td>ACOS(x)</td>
<td>求 x 的反余弦值(参数是弧度)</td>
<td><code>SELECT ACOS(0.25);</code></td>
</tr>
<tr>
<td>ASIN(x)</td>
<td>求反正弦值(参数是弧度)</td>
<td><code>SELECT ASIN(0.25);</code></td>
</tr>
<tr>
<td>ATAN(x)</td>
<td>求反正切值(参数是弧度)</td>
<td><code>SELECT ATAN(2.5);</code></td>
</tr>
<tr>
<td>ATAN2(n, m)</td>
<td>求反正切值(参数是弧度)</td>
<td><code>SELECT ATAN2(-0.8, 2);</code></td>
</tr>
<tr>
<td>AVG(expression)</td>
<td>返回一个表达式的平均值，expression 是一个字段</td>
<td>返回 Products 表中Price 字段的平均值：<code>SELECT AVG(Price) AS AveragePrice FROM Products;</code></td>
</tr>
<tr>
<td>CEIL(x)</td>
<td>返回大于或等于 x 的最小整数</td>
<td><code>SELECT CEIL(1.5) -- 返回2</code></td>
</tr>
<tr>
<td>CEILING(x)</td>
<td>返回大于或等于 x 的最小整数</td>
<td><code>SELECT CEIL(1.5) -- 返回2</code></td>
</tr>
<tr>
<td>COS(x)</td>
<td>求余弦值(参数是弧度)</td>
<td><code>SELECT COS(2);</code></td>
</tr>
<tr>
<td>COT(x)</td>
<td>求余切值(参数是弧度)</td>
<td><code>SELECT COT(6);</code></td>
</tr>
<tr>
<td>COUNT(expression)</td>
<td>返回查询的记录总数，expression 参数是一个字段或者 * 号</td>
<td>返回 Products 表中 products 字段总共有多少条记录：<code>SELECT COUNT(ProductID) AS NumberOfProducts FROM Products;</code></td>
</tr>
<tr>
<td>DEGREES(x)</td>
<td>将弧度转换为角度</td>
<td><code>SELECT DEGREES(3.1415926535898) -- 180</code></td>
</tr>
<tr>
<td>n DIV m</td>
<td>整除，n 为被除数，m 为除数</td>
<td>计算 10 除于 5：<code>SELECT 10 DIV 5;  -- 2</code></td>
</tr>
<tr>
<td>EXP(x)</td>
<td>返回 e 的 x 次方</td>
<td>计算 e 的三次方：<code>SELECT EXP(3) -- 20.085536923188</code></td>
</tr>
<tr>
<td>FLOOR(x)</td>
<td>返回小于或等于 x 的最大整数</td>
<td>小于或等于 1.5 的整数：<code>SELECT FLOOR(1.5) -- 返回1</code></td>
</tr>
<tr>
<td>GREATEST(expr1, expr2, expr3, …)</td>
<td>返回列表中的最大值</td>
<td>返回以下数字列表中的最大值：<code>SELECT GREATEST(3, 12, 34, 8, 25); -- 34</code>返回以下字符串列表中的最大值：<code>SELECT GREATEST(&quot;Google&quot;, &quot;test1&quot;, &quot;Apple&quot;);   -- test1</code></td>
</tr>
<tr>
<td>LEAST(expr1, expr2, expr3, …)</td>
<td>返回列表中的最小值</td>
<td>返回以下数字列表中的最小值：<code>SELECT LEAST(3, 12, 34, 8, 25); -- 3</code>返回以下字符串列表中的最小值：<code>SELECT LEAST(&quot;Google&quot;, &quot;test1&quot;, &quot;Apple&quot;);   -- Apple</code></td>
</tr>
<tr>
<td><a href="http://www.test1.com/mysql/func_mysql_ln.asp" target="_blank" rel="noopener">LN</a></td>
<td>返回数字的自然对数</td>
<td>返回 2 的自然对数：<code>SELECT LN(2);  -- 0.6931471805599453</code></td>
</tr>
<tr>
<td>LOG(x)</td>
<td>返回自然对数(以 e 为底的对数)</td>
<td><code>SELECT LOG(20.085536923188) -- 3</code></td>
</tr>
<tr>
<td>LOG10(x)</td>
<td>返回以 10 为底的对数</td>
<td><code>SELECT LOG10(100) -- 2</code></td>
</tr>
<tr>
<td>LOG2(x)</td>
<td>返回以 2 为底的对数</td>
<td>返回以 2 为底 6 的对数：<code>SELECT LOG2(6);  -- 2.584962500721156</code></td>
</tr>
<tr>
<td>MAX(expression)</td>
<td>返回字段 expression 中的最大值</td>
<td>返回数据表 Products 中字段 Price 的最大值：<code>SELECT MAX(Price) AS LargestPrice FROM Products;</code></td>
</tr>
<tr>
<td>MIN(expression)</td>
<td>返回字段 expression 中的最小值</td>
<td>返回数据表 Products 中字段 Price 的最小值：<code>SELECT MIN(Price) AS LargestPrice FROM Products;</code></td>
</tr>
<tr>
<td>MOD(x,y)</td>
<td>返回 x 除以 y 以后的余数</td>
<td>5 除于 2 的余数：<code>SELECT MOD(5,2) -- 1</code></td>
</tr>
<tr>
<td>PI()</td>
<td>返回圆周率(3.141593）</td>
<td><code>SELECT PI() --3.141593</code></td>
</tr>
<tr>
<td>POW(x,y)</td>
<td>返回 x 的 y 次方</td>
<td>2 的 3 次方：<code>SELECT POW(2,3) -- 8</code></td>
</tr>
<tr>
<td>POWER(x,y)</td>
<td>返回 x 的 y 次方</td>
<td>2 的 3 次方：<code>SELECT POWER(2,3) -- 8</code></td>
</tr>
<tr>
<td>RADIANS(x)</td>
<td>将角度转换为弧度</td>
<td>180 度转换为弧度：<code>SELECT RADIANS(180) -- 3.1415926535898</code></td>
</tr>
<tr>
<td>RAND()</td>
<td>返回 0 到 1 的随机数</td>
<td><code>SELECT RAND() --0.93099315644334</code></td>
</tr>
<tr>
<td>ROUND(x)</td>
<td>返回离 x 最近的整数</td>
<td><code>SELECT ROUND(1.23456) --1</code></td>
</tr>
<tr>
<td>SIGN(x)</td>
<td>返回 x 的符号，x 是负数、0、正数分别返回 -1、0 和 1</td>
<td><code>SELECT SIGN(-10) -- (-1)</code></td>
</tr>
<tr>
<td>SIN(x)</td>
<td>求正弦值(参数是弧度)</td>
<td><code>SELECT SIN(RADIANS(30)) -- 0.5</code></td>
</tr>
<tr>
<td>SQRT(x)</td>
<td>返回x的平方根</td>
<td>25 的平方根：<code>SELECT SQRT(25) -- 5</code></td>
</tr>
<tr>
<td>SUM(expression)</td>
<td>返回指定字段的总和</td>
<td>计算 OrderDetails 表中字段 Quantity 的总和：<code>SELECT SUM(Quantity) AS TotalItemsOrdered FROM OrderDetails;</code></td>
</tr>
<tr>
<td>TAN(x)</td>
<td>求正切值(参数是弧度)</td>
<td><code>SELECT TAN(1.75);  -- -5.52037992250933</code></td>
</tr>
<tr>
<td>TRUNCATE(x,y)</td>
<td>返回数值 x 保留到小数点后 y 位的值（与 ROUND 最大的区别是不会进行四舍五入）</td>
<td><code>SELECT TRUNCATE(1.23456,3) -- 1.234</code></td>
</tr>
</tbody>
</table>
<hr>
<h2 id="15-3、MySQL-日期函数"><a href="#15-3、MySQL-日期函数" class="headerlink" title="15.3、MySQL 日期函数"></a>15.3、MySQL 日期函数</h2><table>
<thead>
<tr>
<th>函数名</th>
<th>描述</th>
<th>实例</th>
</tr>
</thead>
<tbody>
<tr>
<td>ADDDATE(d,n)</td>
<td>计算其实日期 d 加上 n 天的日期</td>
<td><code>SELECT ADDDATE(&quot;2017-06-15&quot;, INTERVAL 10 DAY);-&gt;2017-06-25</code></td>
</tr>
<tr>
<td>ADDTIME(t,n)</td>
<td>时间 t 加上 n 秒的时间</td>
<td><code>SELECT ADDTIME(&#39;2011-11-11 11:11:11&#39;, 5)-&gt;2011-11-11 11:11:16 (秒)</code></td>
</tr>
<tr>
<td>CURDATE()</td>
<td>返回当前日期</td>
<td><code>SELECT CURDATE();-&gt; 2018-09-19</code></td>
</tr>
<tr>
<td>CURRENT_DATE()</td>
<td>返回当前日期</td>
<td><code>SELECT CURRENT_DATE();-&gt; 2018-09-19</code></td>
</tr>
<tr>
<td>CURRENT_TIME</td>
<td>返回当前时间</td>
<td><code>SELECT CURRENT_TIME();-&gt; 19:59:02</code></td>
</tr>
<tr>
<td>CURRENT_TIMESTAMP()</td>
<td>返回当前日期和时间</td>
<td><code>SELECT CURRENT_TIMESTAMP()-&gt; 2018-09-19 20:57:43</code></td>
</tr>
<tr>
<td>CURTIME()</td>
<td>返回当前时间</td>
<td><code>SELECT CURTIME();-&gt; 19:59:02</code></td>
</tr>
<tr>
<td>DATE()</td>
<td>从日期或日期时间表达式中提取日期值</td>
<td><code>SELECT DATE(&quot;2017-06-15&quot;);    -&gt; 2017-06-15</code></td>
</tr>
<tr>
<td>DATEDIFF(d1,d2)</td>
<td>计算日期 d1-&gt;d2 之间相隔的天数</td>
<td><code>SELECT DATEDIFF(&#39;2001-01-01&#39;,&#39;2001-02-02&#39;)-&gt; -32</code></td>
</tr>
<tr>
<td>DATE_ADD(d，INTERVAL expr type)</td>
<td>计算起始日期 d 加上一个时间段后的日期</td>
<td><code>SELECT ADDDATE(&#39;2011-11-11 11:11:11&#39;,1)-&gt; 2011-11-12 11:11:11    (默认是天)SELECT ADDDATE(&#39;2011-11-11 11:11:11&#39;, INTERVAL 5 MINUTE)-&gt; 2011-11-11 11:16:11 (TYPE的取值与上面那个列出来的函数类似)</code></td>
</tr>
<tr>
<td>DATE_FORMAT(d,f)</td>
<td>按表达式 f的要求显示日期 d</td>
<td><code>SELECT DATE_FORMAT(&#39;2011-11-11 11:11:11&#39;,&#39;%Y-%m-%d %r&#39;)-&gt; 2011-11-11 11:11:11 AM</code></td>
</tr>
<tr>
<td>DATE_SUB(date,INTERVAL expr type)</td>
<td>函数从日期减去指定的时间间隔。</td>
<td>Orders 表中 OrderDate 字段减去 2 天：<code>SELECT OrderId,DATE_SUB(OrderDate,INTERVAL 2 DAY) AS OrderPayDateFROM Orders</code></td>
</tr>
<tr>
<td>DAY(d)</td>
<td>返回日期值 d 的日期部分</td>
<td><code>SELECT DAY(&quot;2017-06-15&quot;);  -&gt; 15</code></td>
</tr>
<tr>
<td>DAYNAME(d)</td>
<td>返回日期 d 是星期几，如 Monday,Tuesday</td>
<td><code>SELECT DAYNAME(&#39;2011-11-11 11:11:11&#39;)-&gt;Friday</code></td>
</tr>
<tr>
<td>DAYOFMONTH(d)</td>
<td>计算日期 d 是本月的第几天</td>
<td><code>SELECT DAYOFMONTH(&#39;2011-11-11 11:11:11&#39;)-&gt;11</code></td>
</tr>
<tr>
<td>DAYOFWEEK(d)</td>
<td>日期 d 今天是星期几，1 星期日，2 星期一，以此类推</td>
<td><code>SELECT DAYOFWEEK(&#39;2011-11-11 11:11:11&#39;)-&gt;6</code></td>
</tr>
<tr>
<td>DAYOFYEAR(d)</td>
<td>计算日期 d 是本年的第几天</td>
<td><code>SELECT DAYOFYEAR(&#39;2011-11-11 11:11:11&#39;)-&gt;315</code></td>
</tr>
<tr>
<td>EXTRACT(type FROM d)</td>
<td>从日期 d 中获取指定的值，type 指定返回的值。 type可取值为： MICROSECONDSECONDMINUTEHOURDAYWEEKMONTHQUARTERYEARSECOND_MICROSECONDMINUTE_MICROSECONDMINUTE_SECONDHOUR_MICROSECONDHOUR_SECONDHOUR_MINUTEDAY_MICROSECONDDAY_SECONDDAY_MINUTEDAY_HOURYEAR_MONTH</td>
<td><code>SELECT EXTRACT(MINUTE FROM &#39;2011-11-11 11:11:11&#39;) -&gt; 11</code></td>
</tr>
<tr>
<td>ROM_DAYS(n)</td>
<td>计算从 0000 年 1 月 1 日开始 n 天后的日期</td>
<td><code>SELECT FROM_DAYS(1111)-&gt; 0003-01-16</code></td>
</tr>
<tr>
<td>HOUR(t)</td>
<td>返回 t 中的小时值</td>
<td><code>SELECT HOUR(&#39;1:2:3&#39;)-&gt; 1</code></td>
</tr>
<tr>
<td>LAST_DAY(d)</td>
<td>返回给给定日期的那一月份的最后一天</td>
<td><code>SELECT LAST_DAY(&quot;2017-06-20&quot;);-&gt; 2017-06-30</code></td>
</tr>
<tr>
<td>LOCALTIME()</td>
<td>返回当前日期和时间</td>
<td><code>SELECT LOCALTIME()-&gt; 2018-09-19 20:57:43</code></td>
</tr>
<tr>
<td>LOCALTIMESTAMP()</td>
<td>返回当前日期和时间</td>
<td><code>SELECT LOCALTIMESTAMP()-&gt; 2018-09-19 20:57:43</code></td>
</tr>
<tr>
<td>MAKEDATE(year, day-of-year)</td>
<td>基于给定参数年份 year 和所在年中的天数序号 day-of-year 返回一个日期</td>
<td><code>SELECT MAKEDATE(2017, 3);-&gt; 2017-01-03</code></td>
</tr>
<tr>
<td>MAKETIME(hour, minute, second)</td>
<td>组合时间，参数分别为小时、分钟、秒</td>
<td><code>SELECT MAKETIME(11, 35, 4);-&gt; 11:35:04</code></td>
</tr>
<tr>
<td>MICROSECOND(date)</td>
<td>返回日期参数所对应的毫秒数</td>
<td><code>SELECT MICROSECOND(&quot;2017-06-20 09:34:00.000023&quot;);-&gt; 23</code></td>
</tr>
<tr>
<td>MINUTE(t)</td>
<td>返回 t 中的分钟值</td>
<td><code>SELECT MINUTE(&#39;1:2:3&#39;)-&gt; 2</code></td>
</tr>
<tr>
<td>MONTHNAME(d)</td>
<td>返回日期当中的月份名称，如 Janyary</td>
<td><code>SELECT MONTHNAME(&#39;2011-11-11 11:11:11&#39;)-&gt; November</code></td>
</tr>
<tr>
<td>MONTH(d)</td>
<td>返回日期d中的月份值，1 到 12</td>
<td><code>SELECT MONTH(&#39;2011-11-11 11:11:11&#39;)-&gt;11</code></td>
</tr>
<tr>
<td>NOW()</td>
<td>返回当前日期和时间</td>
<td><code>SELECT NOW()-&gt; 2018-09-19 20:57:43</code></td>
</tr>
<tr>
<td>PERIOD_ADD(period, number)</td>
<td>为 年-月 组合日期添加一个时段</td>
<td><code>SELECT PERIOD_ADD(201703, 5);   -&gt; 201708</code></td>
</tr>
<tr>
<td>PERIOD_DIFF(period1, period2)</td>
<td>返回两个时段之间的月份差值</td>
<td><code>SELECT PERIOD_DIFF(201710, 201703);-&gt; 7</code></td>
</tr>
<tr>
<td>QUARTER(d)</td>
<td>返回日期d是第几季节，返回 1 到 4</td>
<td><code>SELECT QUARTER(&#39;2011-11-11 11:11:11&#39;)-&gt; 4</code></td>
</tr>
<tr>
<td>SECOND(t)</td>
<td>返回 t 中的秒钟值</td>
<td><code>SELECT SECOND(&#39;1:2:3&#39;)-&gt; 3</code></td>
</tr>
<tr>
<td>SEC_TO_TIME(s)</td>
<td>将以秒为单位的时间 s 转换为时分秒的格式</td>
<td><code>SELECT SEC_TO_TIME(4320)-&gt; 01:12:00</code></td>
</tr>
<tr>
<td>STR_TO_DATE(string, format_mask)</td>
<td>将字符串转变为日期</td>
<td><code>SELECT STR_TO_DATE(&quot;August 10 2017&quot;, &quot;%M %d %Y&quot;);-&gt; 2017-08-10</code></td>
</tr>
<tr>
<td>SUBDATE(d,n)</td>
<td>日期 d 减去 n 天后的日期</td>
<td><code>SELECT SUBDATE(&#39;2011-11-11 11:11:11&#39;, 1)-&gt;2011-11-10 11:11:11 (默认是天)</code></td>
</tr>
<tr>
<td>SUBTIME(t,n)</td>
<td>时间 t 减去 n 秒的时间</td>
<td><code>SELECT SUBTIME(&#39;2011-11-11 11:11:11&#39;, 5)-&gt;2011-11-11 11:11:06 (秒)</code></td>
</tr>
<tr>
<td>SYSDATE()</td>
<td>返回当前日期和时间</td>
<td><code>SELECT SYSDATE()-&gt; 2018-09-19 20:57:43</code></td>
</tr>
<tr>
<td>TIME(expression)</td>
<td>提取传入表达式的时间部分</td>
<td><code>SELECT TIME(&quot;19:30:10&quot;);-&gt; 19:30:10</code></td>
</tr>
<tr>
<td>TIME_FORMAT(t,f)</td>
<td>按表达式 f 的要求显示时间 t</td>
<td><code>SELECT TIME_FORMAT(&#39;11:11:11&#39;,&#39;%r&#39;)11:11:11 AM</code></td>
</tr>
<tr>
<td>TIME_TO_SEC(t)</td>
<td>将时间 t 转换为秒</td>
<td><code>SELECT TIME_TO_SEC(&#39;1:12:00&#39;)-&gt; 4320</code></td>
</tr>
<tr>
<td>TIMEDIFF(time1, time2)</td>
<td>计算时间差值</td>
<td><code>SELECT TIMEDIFF(&quot;13:10:11&quot;, &quot;13:10:10&quot;);-&gt; 00:00:01</code></td>
</tr>
<tr>
<td>TIMESTAMP(expression, interval)</td>
<td>单个参数时，函数返回日期或日期时间表达式；有2个参数时，将参数加和</td>
<td><code>SELECT TIMESTAMP(&quot;2017-07-23&quot;,  &quot;13:10:11&quot;);-&gt; 2017-07-23 13:10:11</code></td>
</tr>
<tr>
<td>TO_DAYS(d)</td>
<td>计算日期 d 距离 0000 年 1 月 1 日的天数</td>
<td><code>SELECT TO_DAYS(&#39;0001-01-01 01:01:01&#39;)-&gt; 366</code></td>
</tr>
<tr>
<td>WEEK(d)</td>
<td>计算日期 d 是本年的第几个星期，范围是 0 到 53</td>
<td><code>SELECT WEEK(&#39;2011-11-11 11:11:11&#39;)-&gt; 45</code></td>
</tr>
<tr>
<td>WEEKDAY(d)</td>
<td>日期 d 是星期几，0 表示星期一，1 表示星期二</td>
<td><code>SELECT WEEKDAY(&quot;2017-06-15&quot;);-&gt; 3</code></td>
</tr>
<tr>
<td>WEEKOFYEAR(d)</td>
<td>计算日期 d 是本年的第几个星期，范围是 0 到 53</td>
<td><code>SELECT WEEKOFYEAR(&#39;2011-11-11 11:11:11&#39;)-&gt; 45</code></td>
</tr>
<tr>
<td>YEAR(d)</td>
<td>返回年份</td>
<td><code>SELECT YEAR(&quot;2017-06-15&quot;);-&gt; 2017</code></td>
</tr>
<tr>
<td>YEARWEEK(date, mode)</td>
<td>返回年份及第几周（0到53），mode 中 0 表示周天，1表示周一，以此类推</td>
<td><code>SELECT YEARWEEK(&quot;2017-06-15&quot;);-&gt; 201724</code></td>
</tr>
</tbody>
</table>
<hr>
<h2 id="15-4、MySQL-高级函数"><a href="#15-4、MySQL-高级函数" class="headerlink" title="15.4、MySQL 高级函数"></a>15.4、MySQL 高级函数</h2><table>
<thead>
<tr>
<th>函数名</th>
<th>描述</th>
<th>实例</th>
</tr>
</thead>
<tbody>
<tr>
<td>BIN(x)</td>
<td>返回 x 的二进制编码</td>
<td>15 的 2 进制编码:<code>SELECT BIN(15); -- 1111</code></td>
</tr>
<tr>
<td>BINARY(s)</td>
<td>将字符串 s 转换为二进制字符串</td>
<td><code>SELECT BINARY &quot;test1&quot;;-&gt; test1</code></td>
</tr>
<tr>
<td><code>CASE expression    WHEN condition1 THEN result1    WHEN condition2 THEN result2   ...    WHEN conditionN THEN resultN    ELSE resultEND</code></td>
<td>CASE 表示函数开始，END 表示函数结束。如果 condition1 成立，则返回 result1, 如果 condition2 成立，则返回 result2，当全部不成立则返回 result，而当有一个成立之后，后面的就不执行了。</td>
<td><code>SELECT CASE 　　WHEN 1 &gt; 0　　THEN &#39;1 &gt; 0&#39;　　WHEN 2 &gt; 0　　THEN &#39;2 &gt; 0&#39;　　ELSE &#39;3 &gt; 0&#39;　　END-&gt;1 &gt; 0</code></td>
</tr>
<tr>
<td>CAST(x AS type)</td>
<td>转换数据类型</td>
<td>字符串日期转换为日期：<code>SELECT CAST(&quot;2017-08-29&quot; AS DATE);-&gt; 2017-08-29</code></td>
</tr>
<tr>
<td>COALESCE(expr1, expr2, …., expr_n)</td>
<td>返回参数中的第一个非空表达式（从左向右）</td>
<td><code>SELECT COALESCE(NULL, NULL, NULL, &#39;test1.com&#39;, NULL, &#39;google.com&#39;);-&gt; test1.com</code></td>
</tr>
<tr>
<td>CONNECTION_ID()</td>
<td>返回服务器的连接数</td>
<td><code>SELECT CONNECTION_ID();-&gt; 4292835</code></td>
</tr>
<tr>
<td>CONV(x,f1,f2)</td>
<td>返回 f1 进制数变成 f2 进制数</td>
<td><code>SELECT CONV(15, 10, 2);-&gt; 1111</code></td>
</tr>
<tr>
<td>CONVERT(s USING cs)</td>
<td>函数将字符串 s 的字符集变成 cs</td>
<td><code>SELECT CHARSET(&#39;ABC&#39;)-&gt;utf-8    SELECT CHARSET(CONVERT(&#39;ABC&#39; USING gbk))-&gt;gbk</code></td>
</tr>
<tr>
<td>CURRENT_USER()</td>
<td>返回当前用户</td>
<td><code>SELECT CURRENT_USER();-&gt; guest@%</code></td>
</tr>
<tr>
<td>DATABASE()</td>
<td>返回当前数据库名</td>
<td><code>SELECT DATABASE();   -&gt; test1</code></td>
</tr>
<tr>
<td>IF(expr,v1,v2)</td>
<td>如果表达式 expr 成立，返回结果 v1；否则，返回结果 v2。</td>
<td><code>SELECT IF(1 &gt; 0,&#39;正确&#39;,&#39;错误&#39;)    -&gt;正确</code></td>
</tr>
<tr>
<td><a href="http://www.test1.com/mysql/mysql-func-ifnull.html" target="_blank" rel="noopener">IFNULL(v1,v2)</a></td>
<td>如果 v1 的值不为 NULL，则返回 v1，否则返回 v2。</td>
<td><code>SELECT IFNULL(null,&#39;Hello Word&#39;)-&gt;Hello Word</code></td>
</tr>
<tr>
<td>ISNULL(expression)</td>
<td>判断表达式是否为空</td>
<td><code>SELECT ISNULL(NULL);-&gt;1</code></td>
</tr>
<tr>
<td>LAST_INSERT_ID()</td>
<td>返回最近生成的 AUTO_INCREMENT 值</td>
<td><code>SELECT LAST_INSERT_ID();-&gt;6</code></td>
</tr>
<tr>
<td>NULLIF(expr1, expr2)</td>
<td>比较两个字符串，如果字符串 expr1 与 expr2 相等 返回 NULL，否则返回 expr1</td>
<td><code>SELECT NULLIF(25, 25);-&gt;</code></td>
</tr>
<tr>
<td>SESSION_USER()</td>
<td>返回当前用户</td>
<td><code>SELECT SESSION_USER();-&gt; guest@%</code></td>
</tr>
<tr>
<td>SYSTEM_USER()</td>
<td>返回当前用户</td>
<td><code>SELECT SYSTEM_USER();-&gt; guest@%</code></td>
</tr>
<tr>
<td>USER()</td>
<td>返回当前用户</td>
<td><code>SELECT USER();-&gt; guest@%</code></td>
</tr>
<tr>
<td>VERSION()</td>
<td>返回数据库的版本号</td>
<td><code>SELECT VERSION()-&gt; 5.6.34</code></td>
</tr>
</tbody>
</table>
<h1 id="16、MySQL-索引"><a href="#16、MySQL-索引" class="headerlink" title="16、MySQL 索引"></a>16、MySQL 索引</h1><p>MySQL索引的建立对于MySQL的高效运行是很重要的，索引可以大大提高MySQL的检索速度。</p>
<p>索引分单列索引和组合索引。单列索引，即一个索引只包含单个列，一个表可以有多个单列索引，但这不是组合索引。组合索引，即一个索引包含多个列。</p>
<p>创建索引时，你需要确保该索引是应用在    SQL 查询语句的条件(一般作为 WHERE 子句的条件)。</p>
<p>实际上，索引也是一张表，该表保存了主键与索引字段，并指向实体表的记录。</p>
<p>上面都在说使用索引的好处，但过多的使用索引将会造成滥用。因此索引也会有它的缺点：虽然索引大大提高了查询速度，同时却会降低更新表的速度，如对表进行INSERT、UPDATE和DELETE。因为更新表时，MySQL不仅要保存数据，还要保存一下索引文件。</p>
<p>建立索引会占用磁盘空间的索引文件。</p>
<h2 id="16-1、普通索引"><a href="#16-1、普通索引" class="headerlink" title="16.1、普通索引"></a>16.1、普通索引</h2><h3 id="16-1-1、创建索引"><a href="#16-1-1、创建索引" class="headerlink" title="16.1.1、创建索引"></a>16.1.1、创建索引</h3><p>这是最基本的索引，它没有任何限制。它有以下几种创建方式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">CREATE INDEX indexName ON mytable(username(length)); </span><br><span class="line"></span><br><span class="line">//创建索引</span><br><span class="line"> create index id on B(A_ID);</span><br></pre></td></tr></table></figure>
<p>如果是CHAR，VARCHAR类型，length可以小于字段实际长度；如果是BLOB和TEXT类型，必须指定 length。</p>
<h3 id="16-1-2、修改表结构-添加索引"><a href="#16-1-2、修改表结构-添加索引" class="headerlink" title="16.1.2、修改表结构(添加索引)"></a>16.1.2、修改表结构(添加索引)</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER table tableName ADD INDEX indexName(columnName)</span><br></pre></td></tr></table></figure>
<h3 id="16-1-3、创建表的时候直接指定"><a href="#16-1-3、创建表的时候直接指定" class="headerlink" title="16.1.3、创建表的时候直接指定"></a>16.1.3、创建表的时候直接指定</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE mytable(  </span><br><span class="line"> </span><br><span class="line">ID INT NOT NULL,   </span><br><span class="line"> </span><br><span class="line">username VARCHAR(16) NOT NULL,  </span><br><span class="line"> </span><br><span class="line">INDEX [indexName] (username(length))  </span><br><span class="line"> </span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<h3 id="16-1-4、删除索引的语法"><a href="#16-1-4、删除索引的语法" class="headerlink" title="16.1.4、删除索引的语法"></a>16.1.4、删除索引的语法</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">DROP INDEX [indexName] ON mytable;</span><br></pre></td></tr></table></figure>
<h2 id="16-2、唯一索引"><a href="#16-2、唯一索引" class="headerlink" title="16.2、唯一索引"></a>16.2、唯一索引</h2><p>它与前面的普通索引类似，不同的就是：索引列的值必须唯一，但允许有空值。如果是组合索引，则列值的组合必须唯一。它有以下几种创建方式：</p>
<h3 id="16-2-1、创建索引"><a href="#16-2-1、创建索引" class="headerlink" title="16.2.1、创建索引"></a>16.2.1、创建索引</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CREATE UNIQUE INDEX indexName ON mytable(username(length))</span><br></pre></td></tr></table></figure>
<h3 id="16-2-2、修改表结构"><a href="#16-2-2、修改表结构" class="headerlink" title="16.2.2、修改表结构"></a>16.2.2、修改表结构</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ALTER table mytable ADD UNIQUE [indexName] (username(length))</span><br></pre></td></tr></table></figure>
<h3 id="16-2-3、创建表的时候直接指定"><a href="#16-2-3、创建表的时候直接指定" class="headerlink" title="16.2.3、创建表的时候直接指定"></a>16.2.3、创建表的时候直接指定</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">CREATE TABLE mytable(  </span><br><span class="line"> </span><br><span class="line">ID INT NOT NULL,   </span><br><span class="line"> </span><br><span class="line">username VARCHAR(16) NOT NULL,  </span><br><span class="line"> </span><br><span class="line">UNIQUE [indexName] (username(length))  </span><br><span class="line"> </span><br><span class="line">);</span><br></pre></td></tr></table></figure>
<h2 id="16-3、使用ALTER-命令添加和删除索引"><a href="#16-3、使用ALTER-命令添加和删除索引" class="headerlink" title="16.3、使用ALTER 命令添加和删除索引"></a>16.3、使用ALTER 命令添加和删除索引</h2><p>有四种方式来添加数据表的索引：</p>
<ul>
<li><strong>ALTER TABLE tbl_name ADD PRIMARY KEY (column_list):</strong> 该语句添加一个主键，这意味着索引值必须是唯一的，且不能为NULL。</li>
<li><strong>ALTER TABLE tbl_name ADD UNIQUE index_name (column_list):</strong> 这条语句创建索引的值必须是唯一的（除了NULL外，NULL可能会出现多次）。</li>
<li><strong>ALTER TABLE tbl_name ADD INDEX index_name (column_list):</strong> 添加普通索引，索引值可出现多次。</li>
<li><strong>ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):</strong>该语句指定了索引为 FULLTEXT ，用于全文索引。</li>
</ul>
<p>以下实例为在表中添加索引。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl ADD INDEX (c);</span><br></pre></td></tr></table></figure>
<p>你还可以在 ALTER 命令中使用 DROP 子句来删除索引。尝试以下实例删除索引:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl DROP INDEX c;</span><br></pre></td></tr></table></figure>
<h2 id="16-4、使用-ALTER-命令添加和删除主键"><a href="#16-4、使用-ALTER-命令添加和删除主键" class="headerlink" title="16.4、使用 ALTER 命令添加和删除主键"></a>16.4、使用 ALTER 命令添加和删除主键</h2><p>主键只能作用于一个列上，添加主键索引时，你需要确保该主键默认不为空（NOT NULL）。实例如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl MODIFY test1 INT NOT NULL;</span><br><span class="line">mysql&gt; ALTER TABLE testalter_tbl ADD PRIMARY KEY (test1);</span><br></pre></td></tr></table></figure>
<p>你也可以使用 ALTER 命令删除主键：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; ALTER TABLE testalter_tbl DROP PRIMARY KEY;</span><br></pre></td></tr></table></figure>
<p>删除主键时只需指定PRIMARY KEY，但在删除索引时，你必须知道索引名。</p>
<h2 id="16-5、显示索引信息"><a href="#16-5、显示索引信息" class="headerlink" title="16.5、显示索引信息"></a>16.5、显示索引信息</h2><p>你可以使用 SHOW INDEX 命令来列出表中的相关的索引信息。可以通过添加 \G 来格式化输出信息。</p>
<p>尝试以下实例:</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mysql&gt; SHOW INDEX FROM table_name; \G</span><br></pre></td></tr></table></figure>
<p>mysql&gt; show index from B;<br>+——-+————+———-+————–+————-+———–+————-+———-+——–+——+————+———+—————+<br>| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |<br>+——-+————+———-+————–+————-+———–+————-+———-+——–+——+————+———+—————+<br>| B     |          0 | PRIMARY  |            1 | A_ID        | A         |           3 |     NULL | NULL   |      | BTREE      |         |               |<br>+——-+————+———-+————–+————-+———–+————-+———-+——–+——+————+———+—————+</p>
<h1 id="17、MySQL-事务"><a href="#17、MySQL-事务" class="headerlink" title="17、MySQL 事务"></a>17、MySQL 事务</h1><p>​    MySQL 事务主要用于处理操作量大，复杂度高的数据。比如说，在人员管理系统中，你删除一个人员，你即需要删除人员的基本资料，也要删除和该人员相关的信息，如信箱，文章等等，这样，这些数据库操作语句就构成一个事务！</p>
<ul>
<li>在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。</li>
<li>事务处理可以用来维护数据库的完整性，保证成批的 SQL 语句要么全部执行，要么全部不执行。</li>
<li>事务用来管理 insert,update,delete 语句</li>
</ul>
<p>一般来说，事务是必须满足4个条件（ACID）：：原子性（<strong>A</strong>tomicity，或称不可分割性）、一致性（<strong>C</strong>onsistency）、隔离性（<strong>I</strong>solation，又称独立性）、持久性（<strong>D</strong>urability）。</p>
<ul>
<li><strong>原子性：</strong>一个事务（transaction）中的所有操作，要么全部完成，要么全部不完成，在中间某个环节不会结束。事务在执行过程中发生错误，会被回滚（Rollback）到事务开始前的状态，就像这个事务从来没有执行过一样。</li>
<li><strong>一致性：</strong>在事务开始之前和事务结束以后，数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则，这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。</li>
<li><strong>隔离性：</strong>数据库允许多个并发事务同时对其数据进行读写和修改的能力，隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别，包括读未提交（Read uncommitted）、读提交（read committed）、可重复读（repeatable read）和串行化（Serializable）。</li>
<li><strong>持久性：</strong>事务处理结束后，对数据的修改就是永久的，即便系统故障也不会丢失。</li>
</ul>
<h3 id="17-1、事务控制语句："><a href="#17-1、事务控制语句：" class="headerlink" title="17.1、事务控制语句："></a>17.1、事务控制语句：</h3><ul>
<li>BEGIN或START TRANSACTION；显式地开启一个事务；</li>
<li>COMMIT；也可以使用COMMIT WORK，不过二者是等价的。COMMIT会提交事务，并使已对数据库进行的所有修改成为永久性的；</li>
<li>ROLLBACK；有可以使用ROLLBACK WORK，不过二者是等价的。回滚会结束用户的事务，并撤销正在进行的所有未提交的修改；</li>
<li>SAVEPOINT identifier；SAVEPOINT允许在事务中创建一个保存点，一个事务中可以有多个SAVEPOINT；</li>
<li>RELEASE SAVEPOINT identifier；删除一个事务的保存点，当没有指定的保存点时，执行该语句会抛出一个异常；</li>
<li>ROLLBACK TO identifier；把事务回滚到标记点；</li>
<li>SET TRANSACTION；用来设置事务的隔离级别。InnoDB存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ和SERIALIZABLE。</li>
</ul>
<h3 id="17-2、MYSQL-事务处理主要有两种方法："><a href="#17-2、MYSQL-事务处理主要有两种方法：" class="headerlink" title="17.2、MYSQL 事务处理主要有两种方法："></a>17.2、MYSQL 事务处理主要有两种方法：</h3><p>1、用 BEGIN, ROLLBACK, COMMIT来实现</p>
<ul>
<li><strong>BEGIN</strong> 开始一个事务</li>
<li><strong>ROLLBACK</strong> 事务回滚</li>
<li><strong>COMMIT</strong> 事务确认</li>
</ul>
<p>2、直接用 SET 来改变 MySQL 的自动提交模式:</p>
<ul>
<li><strong>SET AUTOCOMMIT=0</strong> 禁止自动提交</li>
<li><strong>SET AUTOCOMMIT=1</strong> 开启自动提交</li>
</ul>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2019/01/14/mysql/sql_数据库基础/" data-id="ckcc5iwq5009lq4uwdfv7po8s" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/mysql/">mysql</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-vue-select" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2019/01/11/vue-select/" class="article-date">
  <time datetime="2019-01-11T08:42:37.000Z" itemprop="datePublished">2019-01-11</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2019/01/11/vue-select/">vue-select</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h6 id="vue-el-select"><a href="#vue-el-select" class="headerlink" title="vue_el-select"></a>vue_el-select</h6><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">el-select</span> <span class="attr">v-model</span>=<span class="string">"que"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">el-option</span> <span class="attr">v-for</span>=<span class="string">"item in options"</span> <span class="attr">:key</span>=<span class="string">"item.value"</span> <span class="attr">:value</span>=<span class="string">"item.value"</span> <span class="attr">:label</span>=<span class="string">"item.label"</span>&gt;</span><span class="tag">&lt;/<span class="name">el-option</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">el-select</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="javascript"><span class="keyword">export</span> <span class="keyword">default</span>&#123;</span></span><br><span class="line"><span class="undefined">  data() &#123;</span></span><br><span class="line"><span class="javascript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="undefined">      options: [&#123;</span></span><br><span class="line"><span class="undefined">        value: 1,</span></span><br><span class="line"><span class="javascript">        label: <span class="string">'我的'</span></span></span><br><span class="line"><span class="undefined">      &#125;, &#123;</span></span><br><span class="line"><span class="undefined">        value: 2,</span></span><br><span class="line"><span class="javascript">        label: <span class="string">'你的'</span></span></span><br><span class="line"><span class="undefined">      &#125;],</span></span><br><span class="line"><span class="undefined">      que: 2</span></span><br><span class="line"><span class="undefined">    &#125;</span></span><br><span class="line"><span class="undefined">  &#125;</span></span><br><span class="line"><span class="undefined">&#125;</span></span><br><span class="line"><span class="undefined"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="undefined"></span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">el-form-item</span> <span class="attr">label</span>=<span class="string">"订单状态"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">el-select</span>  <span class="attr">placeholder</span>=<span class="string">"订单状态"</span> <span class="attr">v-model</span>=<span class="string">"queryParams.status"</span> <span class="attr">ref</span>=<span class="string">"queryParams.status"</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">el-option</span> <span class="attr">label</span>=<span class="string">"全部"</span> <span class="attr">value</span>=<span class="string">""</span> <span class="attr">name</span>=<span class="string">"status"</span>&gt;</span>全部<span class="tag">&lt;/<span class="name">el-option</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">el-option</span> <span class="attr">label</span>=<span class="string">"已完成"</span> <span class="attr">value</span>=<span class="string">"1"</span> <span class="attr">name</span>=<span class="string">"status"</span>&gt;</span>已完成<span class="tag">&lt;/<span class="name">el-option</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">el-option</span> <span class="attr">label</span>=<span class="string">"未支付"</span> <span class="attr">value</span>=<span class="string">"0"</span> <span class="attr">name</span>=<span class="string">"status"</span>&gt;</span>未支付<span class="tag">&lt;/<span class="name">el-option</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">el-select</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">el-form-item</span>&gt;</span></span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2019/01/11/vue-select/" data-id="ckcc5iwln003nq4uwc0gtmtf1" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/vue/">vue</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-文件上传_springMVCweb" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2019/01/08/文件上传_springMVCweb/" class="article-date">
  <time datetime="2019-01-08T12:42:35.000Z" itemprop="datePublished">2019-01-08</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2019/01/08/文件上传_springMVCweb/">文件上传_springMVCweb</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h5 id="文件上传"><a href="#文件上传" class="headerlink" title="文件上传"></a>文件上传</h5><figure class="highlight tex"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">A form 表单的 enctype 取值必须是： multipart/form-data</span><br><span class="line">(默认值是:application/x-www-form-urlencoded)</span><br><span class="line">enctype:是表单请求正文的类型</span><br><span class="line">B method 属性取值必须是 Post</span><br><span class="line">C 提供一个文件选择域&lt;input type=”file” /&gt;</span><br></pre></td></tr></table></figure>
<h5 id="环境"><a href="#环境" class="headerlink" title="环境"></a>环境</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">web-app</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">display-name</span>&gt;</span>Archetype Created Web Application<span class="tag">&lt;/<span class="name">display-name</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="tag">&lt;<span class="name">servlet</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>dispatcherServlet<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-class</span>&gt;</span>org.springframework.web.servlet.DispatcherServlet<span class="tag">&lt;/<span class="name">servlet-class</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>contextConfigLocation<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>classpath:springmvc.xml<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">load-on-startup</span>&gt;</span>1<span class="tag">&lt;/<span class="name">load-on-startup</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">servlet</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">servlet-name</span>&gt;</span>dispatcherServlet<span class="tag">&lt;/<span class="name">servlet-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">servlet-mapping</span>&gt;</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">&lt;!--配置解决中文乱码的过滤器--&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">filter</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>characterEncodingFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-class</span>&gt;</span>org.springframework.web.filter.CharacterEncodingFilter<span class="tag">&lt;/<span class="name">filter-class</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">init-param</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">param-name</span>&gt;</span>encoding<span class="tag">&lt;/<span class="name">param-name</span>&gt;</span></span><br><span class="line">      <span class="tag">&lt;<span class="name">param-value</span>&gt;</span>UTF-8<span class="tag">&lt;/<span class="name">param-value</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">init-param</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">filter</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">filter-name</span>&gt;</span>characterEncodingFilter<span class="tag">&lt;/<span class="name">filter-name</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">url-pattern</span>&gt;</span>/*<span class="tag">&lt;/<span class="name">url-pattern</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">filter-mapping</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">web-app</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h6 id="springmvc-xml"><a href="#springmvc-xml" class="headerlink" title="springmvc.xml"></a>springmvc.xml</h6><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="php"><span class="meta">&lt;?</span>xml version=<span class="string">"1.0"</span> encoding=<span class="string">"UTF-8"</span><span class="meta">?&gt;</span></span></span><br><span class="line"><span class="tag">&lt;<span class="name">beans</span> <span class="attr">xmlns</span>=<span class="string">"http://www.springframework.org/schema/beans"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:mvc</span>=<span class="string">"http://www.springframework.org/schema/mvc"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:context</span>=<span class="string">"http://www.springframework.org/schema/context"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xmlns:xsi</span>=<span class="string">"http://www.w3.org/2001/XMLSchema-instance"</span></span></span><br><span class="line"><span class="tag">       <span class="attr">xsi:schemaLocation</span>=<span class="string">"</span></span></span><br><span class="line"><span class="tag"><span class="string">        http://www.springframework.org/schema/beans</span></span></span><br><span class="line"><span class="tag"><span class="string">        http://www.springframework.org/schema/beans/spring-beans.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">        http://www.springframework.org/schema/mvc</span></span></span><br><span class="line"><span class="tag"><span class="string">        http://www.springframework.org/schema/mvc/spring-mvc.xsd</span></span></span><br><span class="line"><span class="tag"><span class="string">        http://www.springframework.org/schema/context</span></span></span><br><span class="line"><span class="tag"><span class="string">        http://www.springframework.org/schema/context/spring-context.xsd"</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 开启注解扫描 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">context:component-scan</span> <span class="attr">base-package</span>=<span class="string">"cn.test"</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 视图解析器对象 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"internalResourceViewResolver"</span> <span class="attr">class</span>=<span class="string">"org.springframework.web.servlet.view.InternalResourceViewResolver"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"prefix"</span> <span class="attr">value</span>=<span class="string">"/WEB-INF/pages/"</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"suffix"</span> <span class="attr">value</span>=<span class="string">".jsp"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--前端控制器，哪些静态资源不拦截--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mvc:resources</span> <span class="attr">location</span>=<span class="string">"/css/"</span> <span class="attr">mapping</span>=<span class="string">"/css/**"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mvc:resources</span> <span class="attr">location</span>=<span class="string">"/images/"</span> <span class="attr">mapping</span>=<span class="string">"/images/**"</span>/&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mvc:resources</span> <span class="attr">location</span>=<span class="string">"/js/"</span> <span class="attr">mapping</span>=<span class="string">"/js/**"</span>/&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!--配置文件解析器对象--&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">bean</span> <span class="attr">id</span>=<span class="string">"multipartResolver"</span> <span class="attr">class</span>=<span class="string">"org.springframework.web.multipart.commons.CommonsMultipartResolver"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">property</span> <span class="attr">name</span>=<span class="string">"maxUploadSize"</span> <span class="attr">value</span>=<span class="string">"10485760"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">bean</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">&lt;!-- 开启SpringMVC框架注解的支持 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">mvc:annotation-driven</span> /&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">beans</span>&gt;</span></span><br></pre></td></tr></table></figure>
<h6 id="文件上传-1"><a href="#文件上传-1" class="headerlink" title="文件上传"></a>文件上传</h6><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line"> <span class="tag">&lt;<span class="name">%--</span></span></span><br><span class="line"><span class="tag">  <span class="attr">Created</span> <span class="attr">by</span> <span class="attr">IntelliJ</span> <span class="attr">IDEA.</span></span></span><br><span class="line"><span class="tag">  <span class="attr">User:</span> <span class="attr">Administrator</span></span></span><br><span class="line"><span class="tag">  <span class="attr">Date:</span> <span class="attr">2018</span>/<span class="attr">5</span>/<span class="attr">4</span></span></span><br><span class="line"><span class="tag">  <span class="attr">Time:</span> <span class="attr">21:56</span></span></span><br><span class="line"><span class="tag">  <span class="attr">To</span> <span class="attr">change</span> <span class="attr">this</span> <span class="attr">template</span> <span class="attr">use</span> <span class="attr">File</span> | <span class="attr">Settings</span> | <span class="attr">File</span> <span class="attr">Templates.</span></span></span><br><span class="line"><span class="tag"><span class="attr">--</span>%&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">%@</span> <span class="attr">page</span> <span class="attr">contentType</span>=<span class="string">"text/html;charset=UTF-8"</span> <span class="attr">language</span>=<span class="string">"java"</span> %&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">html</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">title</span>&gt;</span>Title<span class="tag">&lt;/<span class="name">title</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>传统文件上传<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">"/user/fileupload1"</span> <span class="attr">method</span>=<span class="string">"post"</span> <span class="attr">enctype</span>=<span class="string">"multipart/form-data"</span>&gt;</span></span><br><span class="line">        选择文件：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"file"</span> <span class="attr">name</span>=<span class="string">"upload"</span> /&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"submit"</span> <span class="attr">value</span>=<span class="string">"上传"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>Springmvc文件上传<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">"/user/fileupload2"</span> <span class="attr">method</span>=<span class="string">"post"</span> <span class="attr">enctype</span>=<span class="string">"multipart/form-data"</span>&gt;</span></span><br><span class="line">        选择文件：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"file"</span> <span class="attr">name</span>=<span class="string">"upload"</span> /&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"submit"</span> <span class="attr">value</span>=<span class="string">"上传"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">h3</span>&gt;</span>跨服务器文件上传<span class="tag">&lt;/<span class="name">h3</span>&gt;</span></span><br><span class="line"></span><br><span class="line">    <span class="tag">&lt;<span class="name">form</span> <span class="attr">action</span>=<span class="string">"/user/fileupload3"</span> <span class="attr">method</span>=<span class="string">"post"</span> <span class="attr">enctype</span>=<span class="string">"multipart/form-data"</span>&gt;</span></span><br><span class="line">        选择文件：<span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"file"</span> <span class="attr">name</span>=<span class="string">"upload"</span> /&gt;</span><span class="tag">&lt;<span class="name">br</span>/&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">"submit"</span> <span class="attr">value</span>=<span class="string">"上传"</span> /&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span><br></pre></td></tr></table></figure>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 跨服务器文件上传</span></span><br><span class="line"><span class="comment">    * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="meta">@RequestMapping</span>(<span class="string">"/fileupload3"</span>)</span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">fileuoload3</span><span class="params">(MultipartFile upload)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">       System.out.println(<span class="string">"跨服务器文件上传..."</span>);</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 定义上传文件服务器路径</span></span><br><span class="line">       String path = <span class="string">"http://localhost:9090/uploads/"</span>;</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 说明上传文件项</span></span><br><span class="line">       <span class="comment">// 获取上传文件的名称</span></span><br><span class="line">       String filename = upload.getOriginalFilename();</span><br><span class="line">       <span class="comment">// 把文件的名称设置唯一值，uuid</span></span><br><span class="line">       String uuid = UUID.randomUUID().toString().replace(<span class="string">"-"</span>, <span class="string">""</span>);</span><br><span class="line">       filename = uuid+<span class="string">"_"</span>+filename;</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 创建客户端的对象</span></span><br><span class="line">       Client client = Client.create();</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 和图片服务器进行连接</span></span><br><span class="line">       WebResource webResource = client.resource(path + filename);</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 上传文件</span></span><br><span class="line">       webResource.put(upload.getBytes());</span><br><span class="line"></span><br><span class="line">       <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * SpringMVC文件上传</span></span><br><span class="line"><span class="comment">    * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="meta">@RequestMapping</span>(<span class="string">"/fileupload2"</span>)</span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">fileuoload2</span><span class="params">(HttpServletRequest request, MultipartFile upload)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">       System.out.println(<span class="string">"springmvc文件上传..."</span>);</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 使用fileupload组件完成文件上传</span></span><br><span class="line">       <span class="comment">// 上传的位置</span></span><br><span class="line">       String path = request.getSession().getServletContext().getRealPath(<span class="string">"/uploads/"</span>);</span><br><span class="line">       <span class="comment">// 判断，该路径是否存在</span></span><br><span class="line">       File file = <span class="keyword">new</span> File(path);</span><br><span class="line">       <span class="keyword">if</span>(!file.exists())&#123;</span><br><span class="line">           <span class="comment">// 创建该文件夹</span></span><br><span class="line">           file.mkdirs();</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 说明上传文件项</span></span><br><span class="line">       <span class="comment">// 获取上传文件的名称</span></span><br><span class="line">       String filename = upload.getOriginalFilename();</span><br><span class="line">       <span class="comment">// 把文件的名称设置唯一值，uuid</span></span><br><span class="line">       String uuid = UUID.randomUUID().toString().replace(<span class="string">"-"</span>, <span class="string">""</span>);</span><br><span class="line">       filename = uuid+<span class="string">"_"</span>+filename;</span><br><span class="line">       <span class="comment">// 完成文件上传</span></span><br><span class="line">       upload.transferTo(<span class="keyword">new</span> File(path,filename));</span><br><span class="line"></span><br><span class="line">       <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line">   &#125;</span><br><span class="line"></span><br><span class="line">   <span class="comment">/**</span></span><br><span class="line"><span class="comment">    * 文件上传</span></span><br><span class="line"><span class="comment">    * <span class="doctag">@return</span></span></span><br><span class="line"><span class="comment">    */</span></span><br><span class="line">   <span class="meta">@RequestMapping</span>(<span class="string">"/fileupload1"</span>)</span><br><span class="line">   <span class="function"><span class="keyword">public</span> String <span class="title">fileuoload1</span><span class="params">(HttpServletRequest request)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">       System.out.println(<span class="string">"文件上传..."</span>);</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 使用fileupload组件完成文件上传</span></span><br><span class="line">       <span class="comment">// 上传的位置</span></span><br><span class="line">       String path = request.getSession().getServletContext().getRealPath(<span class="string">"/uploads/"</span>);</span><br><span class="line">       <span class="comment">// 判断，该路径是否存在</span></span><br><span class="line">       File file = <span class="keyword">new</span> File(path);</span><br><span class="line">       <span class="keyword">if</span>(!file.exists())&#123;</span><br><span class="line">           <span class="comment">// 创建该文件夹</span></span><br><span class="line">           file.mkdirs();</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       <span class="comment">// 解析request对象，获取上传文件项</span></span><br><span class="line">       DiskFileItemFactory factory = <span class="keyword">new</span> DiskFileItemFactory();</span><br><span class="line">       ServletFileUpload upload = <span class="keyword">new</span> ServletFileUpload(factory);</span><br><span class="line">       <span class="comment">// 解析request</span></span><br><span class="line">       List&lt;FileItem&gt; items = upload.parseRequest(request);</span><br><span class="line">       <span class="comment">// 遍历</span></span><br><span class="line">       <span class="keyword">for</span>(FileItem item:items)&#123;</span><br><span class="line">           <span class="comment">// 进行判断，当前item对象是否是上传文件项</span></span><br><span class="line">           <span class="keyword">if</span>(item.isFormField())&#123;</span><br><span class="line">               <span class="comment">// 说明普通表单向</span></span><br><span class="line">           &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">               <span class="comment">// 说明上传文件项</span></span><br><span class="line">               <span class="comment">// 获取上传文件的名称</span></span><br><span class="line">               String filename = item.getName();</span><br><span class="line">               <span class="comment">// 把文件的名称设置唯一值，uuid</span></span><br><span class="line">               String uuid = UUID.randomUUID().toString().replace(<span class="string">"-"</span>, <span class="string">""</span>);</span><br><span class="line">               filename = uuid+<span class="string">"_"</span>+filename;</span><br><span class="line">               <span class="comment">// 完成文件上传</span></span><br><span class="line">               item.write(<span class="keyword">new</span> File(path,filename));</span><br><span class="line">               <span class="comment">// 删除临时文件</span></span><br><span class="line">               item.delete();</span><br><span class="line">           &#125;</span><br><span class="line">       &#125;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">return</span> <span class="string">"success"</span>;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2019/01/08/文件上传_springMVCweb/" data-id="ckcc5iwm6004jq4uwzg2jprav" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/java/">java</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-nginx文件大小限制" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/29/nginx文件大小限制/" class="article-date">
  <time datetime="2018-12-29T10:40:11.000Z" itemprop="datePublished">2018-12-29</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/29/nginx文件大小限制/">nginx文件大小限制</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h5 id="nginx文件大小限制"><a href="#nginx文件大小限制" class="headerlink" title="nginx文件大小限制"></a>nginx文件大小限制</h5><p>上传超过1M大的客户端文件无法正常上传，nginx直接报错，上传文件太大，于是修改了下nginx的配置，就可以了。<br>按照网上所说的加上client_max_body_size 字段，怎么重启nginx都不行。后来发现放的位置有问题！</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">查询容器</span><br><span class="line">docker ps</span><br><span class="line"></span><br><span class="line">进入容器</span><br><span class="line">docker exec -it e12d7e64036c  /bin/bash</span><br></pre></td></tr></table></figure>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">server &#123;</span><br><span class="line">        listen       80;</span><br><span class="line">        server_name  localhost;</span><br><span class="line">        client_max_body_size 10M;</span><br><span class="line"></span><br><span class="line">        location /web &#123;</span><br><span class="line">            alias   D:/web;</span><br><span class="line">            index main.html;            </span><br><span class="line">        &#125;</span><br><span class="line">        location /web/service &#123;</span><br><span class="line">            proxy_pass   http://192.168.1.188:8080/service;     </span><br><span class="line">        &#125;</span><br><span class="line">        location /web/service/upload &#123;</span><br><span class="line">            proxy_pass   http://192.168.1.188/upload;</span><br><span class="line">        &#125;       </span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
<h3 id="php-ini修改php上传文件大小限制的方法"><a href="#php-ini修改php上传文件大小限制的方法" class="headerlink" title="php.ini修改php上传文件大小限制的方法"></a>php.ini修改php上传文件大小限制的方法</h3><p>vi *.php<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">echo</span> phpinfo();</span><br></pre></td></tr></table></figure></p>
<p>php56 *.php  | grep php.ini</p>
<p>重启 ： /etc/init.d/php56-php-fpm restart</p>
<p>打开php.ini，首先找到<br>file_uploads = on ;是否允许通过HTTP上传文件的开关。默认为ON即是开<br>upload_tmp_dir ;文件上传至服务器上存储临时文件的地方，如果没指定就会用系统默认的临时文件夹<br>upload_max_filesize = 8m ;望文生意，即允许上传文件大小的最大值。默认为2M<br>post_max_size = 8m ;指通过表单POST给PHP的所能接收的最大值，包括表单里的所有值。默认为8M<br>一般地，设置好上述四个参数后，上传&lt;=8M的文件是不成问题，在网络正常的情况下。<br>但如果要上传&gt;8M的大体积文件，只设置上述四项还一定能行的通。</p>
<p>进一步配置以下的参数<br>max_execution_time = 600 ;每个PHP页面运行的最大时间值(秒)，默认30秒<br>max_input_time = 600 ;每个PHP页面接收数据所需的最大时间，默认60秒<br>memory_limit = 8m ;每个PHP页面所吃掉的最大内存，默认8M<br>把上述参数修改后，在网络所允许的正常情况下，就可以上传大体积文件了<br>max_execution_time = 600<br>max_input_time = 600<br>memory_limit = 32m<br>file_uploads = on<br>upload_tmp_dir = /tmp<br>upload_max_filesize = 32m<br>post_max_size = 32m</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/29/nginx文件大小限制/" data-id="ckcc5iwkz002lq4uwsgeb3xop" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/linux/">linux</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-Docker" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/28/Docker/" class="article-date">
  <time datetime="2018-12-28T10:56:26.000Z" itemprop="datePublished">2018-12-28</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/28/Docker/">Docker</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="Docker"><a href="#Docker" class="headerlink" title="Docker"></a>Docker</h2><h2 id="1-Docker简介"><a href="#1-Docker简介" class="headerlink" title="1 Docker简介"></a>1 Docker简介</h2><h2 id="1-1-什么是虚拟化"><a href="#1-1-什么是虚拟化" class="headerlink" title="1.1 什么是虚拟化"></a>1.1 什么是虚拟化</h2><p>​    在计算机中，虚拟化（英语：Virtualization）是一种资源管理技术，是将计算机的各种实体资源，如服务器、网络、内存及存储等，予以抽象、转换后呈现出来，打破实体结构间的不可切割的障碍，使用户可以比原本的组态更好的方式来应用这些资源。这些资源的新虚拟部份是不受现有资源的架设方式，地域或物理组态所限制。一般所指的虚拟化资源包括计算能力和资料存储。</p>
<p>​    在实际的生产环境中，虚拟化技术主要用来解决高性能的物理硬件产能过剩和老的旧的硬件产能过低的重组重用，透明化底层物理硬件，从而最大化的利用物理硬件   对资源充分利用</p>
<p>​    虚拟化技术种类很多，例如：软件虚拟化、硬件虚拟化、内存虚拟化、网络虚拟化(vip)、桌面虚拟化、服务虚拟化、虚拟机等等。</p>
<h2 id="1-2-什么是Docker"><a href="#1-2-什么是Docker" class="headerlink" title="1.2 什么是Docker"></a>1.2 什么是Docker</h2><p>​    Docker 是一个开源项目，诞生于 2013 年初，最初是 dotCloud 公司内部的一个业余项目。它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会，遵从了 Apache 2.0 协议，项目代码在 <a href="https://github.com/docker/docker" target="_blank" rel="noopener">GitHub</a> 上进行维护。</p>
<p>​    <img src="https://threadv.github.io/docker_image/1-3.png" alt="1-3"></p>
<p>​    Docker 自开源后受到广泛的关注和讨论，以至于 dotCloud 公司后来都改名为 Docker Inc。Redhat 已经在其 RHEL6.5 中集中支持 Docker；Google 也在其 PaaS 产品中广泛应用。</p>
<p>​    Docker 项目的目标是实现轻量级的操作系统虚拟化解决方案。 Docker 的基础是 Linux 容器（LXC）等技术。</p>
<p>​    在 LXC 的基础上 Docker 进行了进一步的封装，让用户不需要去关心容器的管理，使得操作更为简便。用户操作 Docker 的容器就像操作一个快速轻量级的虚拟机一样简单。</p>
<p>为什么选择Docker?</p>
<p>（1）上手快。</p>
<p>​    用户只需要几分钟，就可以把自己的程序“Docker化”。Docker依赖于“写时复制”（copy-on-write）模型，使修改应用程序也非常迅速，可以说达到“随心所致，代码即改”的境界。    </p>
<pre><code>随后，就可以创建容器来运行应用程序了。大多数Docker容器只需要不到1秒中即可启动。由于去除了管理程序的开销，Docker容器拥有很高的性能，同时同一台宿主机中也可以运行更多的容器，使用户尽可能的充分利用系统资源。
</code></pre><p>（2）职责的逻辑分类</p>
<p>​    使用Docker，开发人员只需要关心容器中运行的应用程序，而运维人员只需要关心如何管理容器。Docker设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署的生产环境一致性。从而降低那种“开发时一切正常，肯定是运维的问题（测试环境都是正常的，上线后出了问题就归结为肯定是运维的问题）”</p>
<p>（3）快速高效的开发生命周期</p>
<p>​    Docker的目标之一就是缩短代码从开发、测试到部署、上线运行的周期，让你的应用程序具备可移植性，易于构建，并易于协作。（通俗一点说，Docker就像一个盒子，里面可以装很多物件，如果需要这些物件的可以直接将该大盒子拿走，而不需要从该盒子中一件件的取。）</p>
<p>（4）鼓励使用面向服务的架构</p>
<p>​    Docker还鼓励面向服务的体系结构和微服务架构。Docker推荐单个容器只运行一个应用程序或进程，这样就形成了一个分布式的应用程序模型，在这种模型下，应用程序或者服务都可以表示为一系列内部互联的容器，从而使分布式部署应用程序，扩展或调试应用程序都变得非常简单，同时也提高了程序的内省性。（当然，可以在一个容器中运行多个应用程序）</p>
<h2 id="1-3-容器与虚拟机比较"><a href="#1-3-容器与虚拟机比较" class="headerlink" title="1.3 容器与虚拟机比较"></a>1.3 容器与虚拟机比较</h2><p>​    下面的图片比较了 Docker 和传统虚拟化方式的不同之处，可见容器是在操作系统层面上实现虚拟化，直接复用本地主机的操作系统，而传统方式则是在硬件层面实现。</p>
<p><img src="https://threadv.github.io/docker_image/1-1.png" alt=""></p>
<p>与传统的虚拟机相比，Docker优势体现为启动速度快、占用体积小。</p>
<h2 id="1-4-Docker-组件"><a href="#1-4-Docker-组件" class="headerlink" title="1.4 Docker 组件"></a>1.4 Docker 组件</h2><h3 id="1-4-1-Docker服务器与客户端"><a href="#1-4-1-Docker服务器与客户端" class="headerlink" title="1.4.1 Docker服务器与客户端"></a>1.4.1 Docker服务器与客户端</h3><p>​    Docker是一个客户端-服务器（C/S）架构程序。Docker客户端只需要向Docker服务器或者守护进程发出请求，服务器或者守护进程将完成所有工作并返回结果。Docker提供了一个命令行工具Docker以及一整套RESTful API。你可以在同一台宿主机上运行Docker守护进程和客户端，也可以从本地的Docker客户端连接到运行在另一台宿主机上的远程Docker守护进程。</p>
<p><img src="https://threadv.github.io/docker_image/1-2.png" alt=""></p>
<h3 id="1-4-2-Docker镜像与容器"><a href="#1-4-2-Docker镜像与容器" class="headerlink" title="1.4.2 Docker镜像与容器"></a>1.4.2 Docker镜像与容器</h3><p>​    镜像是构建Docker的基石。用户基于镜像来运行自己的容器。镜像也是Docker生命周期中的“构建”部分。镜像是基于联合文件系统的一种层式结构，由一系列指令一步一步构建出来。例如：</p>
<p>添加一个文件；</p>
<p>执行一个命令；</p>
<p>打开一个窗口。</p>
<p>也可以将镜像当作容器的“源代码”。镜像体积很小，非常“便携”，易于分享、存储和更新。</p>
<p>​    Docker可以帮助你构建和部署容器，你只需要把自己的应用程序或者服务打包放进容器即可。容器是基于镜像启动起来的，容器中可以运行一个或多个进程。我们可以认为，镜像是Docker生命周期中的构建或者打包阶段，而容器则是启动或者执行阶段。  容器基于镜像启动，一旦容器启动完成后，我们就可以登录到容器中安装自己需要的软件或者服务。</p>
<p>所以Docker容器就是：</p>
<p>​    一个镜像格式；</p>
<p>​    一些列标准操作；</p>
<p>​    一个执行环境。</p>
<p>​    Docker借鉴了标准集装箱的概念。标准集装箱将货物运往世界各地，Docker将这个模型运用到自己的设计中，唯一不同的是：集装箱运输货物，而Docker运输软件。</p>
<pre><code>和集装箱一样，Docker在执行上述操作时，并不关心容器中到底装了什么，它不管是web服务器，还是数据库，或者是应用程序服务器什么的。所有的容器都按照相同的方式将内容“装载”进去。

Docker也不关心你要把容器运到何方：我们可以在自己的笔记本中构建容器，上传到Registry，然后下载到一个物理的或者虚拟的服务器来测试，在把容器部署到具体的主机中。像标准集装箱一样，Docker容器方便替换，可以叠加，易于分发，并且尽量通用。
</code></pre><h3 id="1-4-3-Registry（注册中心）"><a href="#1-4-3-Registry（注册中心）" class="headerlink" title="1.4.3 Registry（注册中心）"></a>1.4.3 Registry（注册中心）</h3><p>​    Docker用Registry来保存用户构建的镜像。Registry分为公共和私有两种。Docker公司运营公共的Registry叫做Docker Hub。用户可以在Docker Hub注册账号，分享并保存自己的镜像（说明：在Docker Hub下载镜像巨慢，可以自己构建私有的Registry）。</p>
<p>​    <a href="https://hub.docker.com/" target="_blank" rel="noopener">https://hub.docker.com/</a></p>
<h1 id="2-Docker安装与启动"><a href="#2-Docker安装与启动" class="headerlink" title="2 Docker安装与启动"></a>2 Docker安装与启动</h1><h2 id="2-1-安装Docker"><a href="#2-1-安装Docker" class="headerlink" title="2.1 安装Docker"></a>2.1 安装Docker</h2><p>​    Docker官方建议在Ubuntu中安装，因为Docker是基于Ubuntu发布的，而且一般Docker出现的问题Ubuntu是最先更新或者打补丁的。在很多版本的CentOS中是不支持更新最新的一些补丁包的。</p>
<p>​    由于我们学习的环境都使用的是CentOS，因此这里我们将Docker安装到CentOS上。注意：这里建议安装在CentOS7.x以上的版本，在CentOS6.x的版本中，安装前需要安装其他很多的环境而且Docker很多补丁不支持更新。</p>
<p>​    请直接挂载课程配套的Centos7.x镜像    </p>
<p>（1）yum 包更新到最新</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo yum update</span><br></pre></td></tr></table></figure>
<p>（2）安装需要的软件包， yum-util 提供yum-config-manager功能，另外两个是devicemapper驱动依赖的</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install -y yum-utils device-mapper-persistent-data lvm2</span><br></pre></td></tr></table></figure>
<p>（3）设置yum源为阿里云</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo</span><br></pre></td></tr></table></figure>
<p>（4）安装docker</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo yum install docker-ce</span><br></pre></td></tr></table></figure>
<p>（5）安装后查看docker版本</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker -v</span><br></pre></td></tr></table></figure>
<h2 id="2-2-设置ustc的镜像"><a href="#2-2-设置ustc的镜像" class="headerlink" title="2.2 设置ustc的镜像"></a>2.2 设置ustc的镜像</h2><p>ustc是老牌的linux镜像服务提供者了，还在遥远的ubuntu 5.04版本的时候就在用。ustc的docker镜像加速器速度很快。ustc docker mirror的优势之一就是不需要注册，是真正的公共服务。</p>
<p><a href="https://lug.ustc.edu.cn/wiki/mirrors/help/docker" target="_blank" rel="noopener">https://lug.ustc.edu.cn/wiki/mirrors/help/docker</a></p>
<p>编辑该文件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/docker/daemon.json</span><br></pre></td></tr></table></figure>
<p>在该文件中输入如下内容：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">&quot;registry-mirrors&quot;: [&quot;https://docker.mirrors.ustc.edu.cn&quot;]</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="2-3-Docker的启动与停止"><a href="#2-3-Docker的启动与停止" class="headerlink" title="2.3 Docker的启动与停止"></a>2.3 Docker的启动与停止</h2><p><strong>systemctl</strong>命令是系统服务管理器指令</p>
<p>启动docker：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl start docker</span><br></pre></td></tr></table></figure>
<p>停止docker：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl stop docker</span><br></pre></td></tr></table></figure>
<p>重启docker：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure>
<p>查看docker状态：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl status docker</span><br></pre></td></tr></table></figure>
<p>开机启动：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl enable docker</span><br></pre></td></tr></table></figure>
<p>查看docker概要信息</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker info</span><br></pre></td></tr></table></figure>
<p>查看docker帮助文档</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker --help</span><br></pre></td></tr></table></figure>
<h1 id="3-常用命令"><a href="#3-常用命令" class="headerlink" title="3 常用命令"></a>3 常用命令</h1><h2 id="3-1-镜像相关命令"><a href="#3-1-镜像相关命令" class="headerlink" title="3.1 镜像相关命令"></a>3.1 镜像相关命令</h2><h3 id="3-1-1-查看镜像"><a href="#3-1-1-查看镜像" class="headerlink" title="3.1.1 查看镜像"></a>3.1.1 查看镜像</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker https://threadv.github.io/docker_images</span><br></pre></td></tr></table></figure>
<p>REPOSITORY：镜像名称</p>
<p>TAG：镜像标签</p>
<p><a href="https://threadv.github.io/docker_image" target="_blank" rel="noopener">https://threadv.github.io/docker_image</a> ID：镜像ID</p>
<p>CREATED：镜像的创建日期（不是获取该镜像的日期）</p>
<p>SIZE：镜像大小</p>
<p>这些镜像都是存储在Docker宿主机的/var/lib/docker目录下</p>
<h3 id="3-1-2-搜索镜像"><a href="#3-1-2-搜索镜像" class="headerlink" title="3.1.2 搜索镜像"></a>3.1.2 搜索镜像</h3><p>如果你需要从网络中查找需要的镜像，可以通过以下命令搜索</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker search 镜像名称</span><br></pre></td></tr></table></figure>
<p>NAME：仓库名称</p>
<p>DESCRIPTION：镜像描述</p>
<p>STARS：用户评价，反应一个镜像的受欢迎程度</p>
<p>OFFICIAL：是否官方</p>
<p>AUTOMATED：自动构建，表示该镜像由Docker Hub自动构建流程创建的</p>
<h3 id="3-1-3-拉取镜像"><a href="#3-1-3-拉取镜像" class="headerlink" title="3.1.3 拉取镜像"></a>3.1.3 拉取镜像</h3><p>拉取镜像就是从中央仓库中下载镜像到本地</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull 镜像名称</span><br></pre></td></tr></table></figure>
<p>例如，我要下载centos7镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull centos:7</span><br></pre></td></tr></table></figure>
<h3 id="3-1-4-删除镜像"><a href="#3-1-4-删除镜像" class="headerlink" title="3.1.4 删除镜像"></a>3.1.4 删除镜像</h3><p>按镜像ID删除镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker rmi 镜像ID</span><br></pre></td></tr></table></figure>
<p>删除所有镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker rmi `docker https://threadv.github.io/docker_images -q`</span><br></pre></td></tr></table></figure>
<h2 id="3-2-容器相关命令"><a href="#3-2-容器相关命令" class="headerlink" title="3.2 容器相关命令"></a>3.2 容器相关命令</h2><h3 id="3-2-1-查看容器"><a href="#3-2-1-查看容器" class="headerlink" title="3.2.1 查看容器"></a>3.2.1 查看容器</h3><p>查看正在运行的容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker ps</span><br></pre></td></tr></table></figure>
<p>查看所有容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker ps –a</span><br></pre></td></tr></table></figure>
<p>查看最后一次运行的容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker ps –l</span><br></pre></td></tr></table></figure>
<p>查看停止的容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker ps -f status=exited</span><br></pre></td></tr></table></figure>
<h3 id="3-2-2-创建与启动容器"><a href="#3-2-2-创建与启动容器" class="headerlink" title="3.2.2 创建与启动容器"></a>3.2.2 创建与启动容器</h3><p>创建容器常用的参数说明：</p>
<p>创建容器命令：docker run</p>
<p> -i：表示运行容器</p>
<p> -t：表示容器启动后会进入其命令行。加入这两个参数后，容器创建就能登录进去。即分配一个伪终端。</p>
<p> –name :为创建的容器命名。</p>
<p> -v：表示目录映射关系（前者是宿主机目录，后者是映射到宿主机上的目录），可以使用多个－v做多个目录或文件映射。注意：最好做目录映射，在宿主机上做修改，然后共享到容器上。</p>
<p> -d：在run后面加上-d参数,则会创建一个守护式容器在后台运行（这样创建容器后不会自动登录容器，如果只加-i -t两个参数，创建后就会自动进去容器）。</p>
<p> -p：表示端口映射，前者是宿主机端口，后者是容器内的映射端口。可以使用多个-p做多个端口映射</p>
<p>（1）交互式方式创建容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -it --name=容器名称 镜像名称:标签 /bin/bash</span><br></pre></td></tr></table></figure>
<p>这时我们通过ps命令查看，发现可以看到启动的容器，状态为启动状态  </p>
<p>退出当前容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">exit</span><br></pre></td></tr></table></figure>
<p>（2）守护式方式创建容器：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -di --name=容器名称 镜像名称:标签</span><br></pre></td></tr></table></figure>
<p>登录守护式容器方式：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker exec -it 容器名称 (或者容器ID)  /bin/bash</span><br></pre></td></tr></table></figure>
<h3 id="3-2-3-停止与启动容器"><a href="#3-2-3-停止与启动容器" class="headerlink" title="3.2.3 停止与启动容器"></a>3.2.3 停止与启动容器</h3><p>停止容器：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker stop 容器名称（或者容器ID）</span><br></pre></td></tr></table></figure>
<p>启动容器：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker start 容器名称（或者容器ID）</span><br></pre></td></tr></table></figure>
<h3 id="3-2-4-文件拷贝"><a href="#3-2-4-文件拷贝" class="headerlink" title="3.2.4 文件拷贝"></a>3.2.4 文件拷贝</h3><p>如果我们需要将文件拷贝到容器内可以使用cp命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker cp 需要拷贝的文件或目录 容器名称:容器目录</span><br></pre></td></tr></table></figure>
<p>也可以将文件从容器内拷贝出来</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker cp 容器名称:容器目录 需要拷贝的文件或目录</span><br></pre></td></tr></table></figure>
<h3 id="3-2-5-目录挂载"><a href="#3-2-5-目录挂载" class="headerlink" title="3.2.5 目录挂载"></a>3.2.5 目录挂载</h3><p>我们可以在创建容器的时候，将宿主机的目录与容器内的目录进行映射，这样我们就可以通过修改宿主机某个目录的文件从而去影响容器。<br>创建容器 添加-v参数 后边为   宿主机目录:容器目录，例如：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -di -v /usr/local/myhtml:/usr/local/myhtml --name=mycentos3 centos:7</span><br></pre></td></tr></table></figure>
<p>如果你共享的是多级的目录，可能会出现权限不足的提示。</p>
<p>这是因为CentOS7中的安全模块selinux把权限禁掉了，我们需要添加参数  –privileged=true  来解决挂载的目录没有权限的问题</p>
<h3 id="3-2-6-查看容器IP地址"><a href="#3-2-6-查看容器IP地址" class="headerlink" title="3.2.6 查看容器IP地址"></a>3.2.6 查看容器IP地址</h3><p>我们可以通过以下命令查看容器运行的各种数据</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker inspect 容器名称（容器ID）</span><br></pre></td></tr></table></figure>
<p>也可以直接执行下面的命令直接输出IP地址</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker inspect --format=&apos;&#123;&#123;.NetworkSettings.IPAddress&#125;&#125;&apos; 容器名称（容器ID）</span><br></pre></td></tr></table></figure>
<h3 id="3-2-7-删除容器"><a href="#3-2-7-删除容器" class="headerlink" title="3.2.7 删除容器"></a>3.2.7 删除容器</h3><p>删除指定的容器：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker rm 容器名称（容器ID）</span><br></pre></td></tr></table></figure>
<h1 id="4-应用部署"><a href="#4-应用部署" class="headerlink" title="4 应用部署"></a>4 应用部署</h1><h2 id="4-1-MySQL部署"><a href="#4-1-MySQL部署" class="headerlink" title="4.1 MySQL部署"></a>4.1 MySQL部署</h2><p>（1）拉取mysql镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull centos/mysql-57-centos7</span><br></pre></td></tr></table></figure>
<p>（2）创建容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -di --name=tensquare_mysql -p 33306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql</span><br></pre></td></tr></table></figure>
<p>-p 代表端口映射，格式为  宿主机映射端口:容器运行端口</p>
<p>-e 代表添加环境变量  MYSQL_ROOT_PASSWORD  是root用户的登陆密码</p>
<p>（3）远程登录mysql</p>
<p>连接宿主机的IP  ,指定端口为33306 </p>
<h2 id="4-2-tomcat部署"><a href="#4-2-tomcat部署" class="headerlink" title="4.2 tomcat部署"></a>4.2 tomcat部署</h2><p>（1）拉取镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull tomcat:7-jre7</span><br></pre></td></tr></table></figure>
<p>（2）创建容器</p>
<p>创建容器  -p表示地址映射</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">docker run -di --name=mytomcat -p 9000:8080 </span><br><span class="line">-v /usr/local/webapps:/usr/local/tomcat/webapps tomcat:7-jre7</span><br></pre></td></tr></table></figure>
<h2 id="4-3-Nginx部署"><a href="#4-3-Nginx部署" class="headerlink" title="4.3 Nginx部署"></a>4.3 Nginx部署</h2><p>（1）拉取镜像    </p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull nginx</span><br></pre></td></tr></table></figure>
<p>（2）创建Nginx容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -di --name=mynginx -p 80:80 nginx</span><br></pre></td></tr></table></figure>
<h2 id="4-4-Redis部署"><a href="#4-4-Redis部署" class="headerlink" title="4.4 Redis部署"></a>4.4 Redis部署</h2><p>（1）拉取镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull redis</span><br></pre></td></tr></table></figure>
<p>（2）创建容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -di --name=myredis -p 6379:6379 redis</span><br></pre></td></tr></table></figure>
<h1 id="5-迁移与备份"><a href="#5-迁移与备份" class="headerlink" title="5 迁移与备份"></a>5 迁移与备份</h1><h2 id="5-1-容器保存为镜像"><a href="#5-1-容器保存为镜像" class="headerlink" title="5.1 容器保存为镜像"></a>5.1 容器保存为镜像</h2><p>我们可以通过以下命令将容器保存为镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker commit mynginx mynginx_i</span><br></pre></td></tr></table></figure>
<h2 id="5-2-镜像备份"><a href="#5-2-镜像备份" class="headerlink" title="5.2 镜像备份"></a>5.2 镜像备份</h2><p>我们可以通过以下命令将镜像保存为tar 文件</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker  save -o mynginx.tar mynginx_i</span><br></pre></td></tr></table></figure>
<h2 id="5-3-镜像恢复与迁移"><a href="#5-3-镜像恢复与迁移" class="headerlink" title="5.3 镜像恢复与迁移"></a>5.3 镜像恢复与迁移</h2><p>首先我们先删除掉mynginx_img镜像  然后执行此命令进行恢复</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker load -i mynginx.tar</span><br></pre></td></tr></table></figure>
<p>-i 输入的文件</p>
<p>执行后再次查看镜像，可以看到镜像已经恢复</p>
<h1 id="6-Dockerfile"><a href="#6-Dockerfile" class="headerlink" title="6 Dockerfile"></a>6 Dockerfile</h1><h2 id="6-1-什么是Dockerfile"><a href="#6-1-什么是Dockerfile" class="headerlink" title="6.1 什么是Dockerfile"></a>6.1 什么是Dockerfile</h2><p>Dockerfile是由一系列命令和参数构成的脚本，这些命令应用于基础镜像并最终创建一个新的镜像。</p>
<p>1、对于开发人员：可以为开发团队提供一个完全一致的开发环境；<br>2、对于测试人员：可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了；<br>3、对于运维人员：在部署时，可以实现应用的无缝移植。</p>
<h2 id="6-2-常用命令"><a href="#6-2-常用命令" class="headerlink" title="6.2 常用命令"></a>6.2 常用命令</h2><table>
<thead>
<tr>
<th>命令</th>
<th>作用</th>
</tr>
</thead>
<tbody>
<tr>
<td>FROM <a href="https://threadv.github.io/docker_image_name:tag" target="_blank" rel="noopener">https://threadv.github.io/docker_image_name:tag</a></td>
<td>定义了使用哪个基础镜像启动构建流程</td>
</tr>
<tr>
<td>MAINTAINER user_name</td>
<td>声明镜像的创建者</td>
</tr>
<tr>
<td>ENV key value</td>
<td>设置环境变量 (可以写多条)</td>
</tr>
<tr>
<td>RUN command</td>
<td>是Dockerfile的核心部分(可以写多条)</td>
</tr>
<tr>
<td>ADD source_dir/file dest_dir/file</td>
<td>将宿主机的文件复制到容器内，如果是一个压缩文件，将会在复制后自动解压</td>
</tr>
<tr>
<td>COPY source_dir/file dest_dir/file</td>
<td>和ADD相似，但是如果有压缩文件并不能解压</td>
</tr>
<tr>
<td>WORKDIR path_dir</td>
<td>设置工作目录</td>
</tr>
</tbody>
</table>
<h2 id="6-3-使用脚本创建镜像"><a href="#6-3-使用脚本创建镜像" class="headerlink" title="6.3 使用脚本创建镜像"></a>6.3 使用脚本创建镜像</h2><p>步骤：</p>
<p>（1）创建目录</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir –p /usr/local/dockerjdk8</span><br></pre></td></tr></table></figure>
<p>（2）下载jdk-8u171-linux-x64.tar.gz并上传到服务器（虚拟机）中的/usr/local/dockerjdk8目录</p>
<p>（3）创建文件Dockerfile  <code>vi Dockerfile</code></p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">#依赖镜像名称和ID</span><br><span class="line">FROM centos:7</span><br><span class="line">#指定镜像创建者信息</span><br><span class="line">MAINTAINER ITCAST</span><br><span class="line">#切换工作目录</span><br><span class="line">WORKDIR /usr</span><br><span class="line">RUN mkdir  /usr/local/java</span><br><span class="line">#ADD 是相对路径jar,把java添加到容器中</span><br><span class="line">ADD jdk-8u171-linux-x64.tar.gz /usr/local/java/</span><br><span class="line"></span><br><span class="line">#配置java环境变量</span><br><span class="line">ENV JAVA_HOME /usr/local/java/jdk1.8.0_171</span><br><span class="line">ENV JRE_HOME $JAVA_HOME/jre</span><br><span class="line">ENV CLASSPATH $JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib:$CLASSPATH</span><br><span class="line">ENV PATH $JAVA_HOME/bin:$PATH</span><br></pre></td></tr></table></figure>
<p>（4）执行命令构建镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker build -t=&apos;jdk1.8&apos; .</span><br></pre></td></tr></table></figure>
<p>注意后边的空格和点，不要省略</p>
<p>（5）查看镜像是否建立完成</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker https://threadv.github.io/docker_images</span><br></pre></td></tr></table></figure>
<h1 id="7-Docker私有仓库"><a href="#7-Docker私有仓库" class="headerlink" title="7 Docker私有仓库"></a>7 Docker私有仓库</h1><h2 id="7-1-私有仓库搭建与配置"><a href="#7-1-私有仓库搭建与配置" class="headerlink" title="7.1 私有仓库搭建与配置"></a>7.1 私有仓库搭建与配置</h2><p>（1）拉取私有仓库镜像（此步省略）</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker pull registry</span><br></pre></td></tr></table></figure>
<p>（2）启动私有仓库容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker run -di --name=registry -p 5000:5000 registry</span><br></pre></td></tr></table></figure>
<p>（3）打开浏览器 输入地址<a href="http://192.168.184.141:5000/v2/_catalog看到`{&quot;repositories&quot;:[]}`" target="_blank" rel="noopener">http://192.168.184.141:5000/v2/_catalog看到`{&quot;repositories&quot;:[]}`</a> 表示私有仓库搭建成功并且内容为空</p>
<p>（4）修改daemon.json</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/docker/daemon.json</span><br></pre></td></tr></table></figure>
<p>添加以下内容，保存退出。</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">"insecure-registries"</span>:[<span class="string">"192.168.184.141:5000"</span>]&#125;</span><br></pre></td></tr></table></figure>
<p>此步用于让 docker信任私有仓库地址</p>
<p>（5）重启docker 服务</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">systemctl restart docker</span><br></pre></td></tr></table></figure>
<h2 id="7-2-镜像上传至私有仓库"><a href="#7-2-镜像上传至私有仓库" class="headerlink" title="7.2 镜像上传至私有仓库"></a>7.2 镜像上传至私有仓库</h2><p>（1）标记此镜像为私有仓库的镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker tag jdk1.8 192.168.184.141:5000/jdk1.8</span><br></pre></td></tr></table></figure>
<p>（2）再次启动私服容器</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker start registry</span><br></pre></td></tr></table></figure>
<p>（3）上传标记的镜像</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">docker push 192.168.184.141:5000/jdk1.8</span><br></pre></td></tr></table></figure>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/28/Docker/" data-id="ckcc5iwib0003q4uwemsfwuy9" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/docker/">docker</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-JVM-优化" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/28/JVM-优化/" class="article-date">
  <time datetime="2018-12-28T02:50:35.000Z" itemprop="datePublished">2018-12-28</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/28/JVM-优化/">JVM-优化</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="JVM-优化"><a href="#JVM-优化" class="headerlink" title="JVM-优化"></a>JVM-优化</h2><h2 id="1、Tomcat8优化"><a href="#1、Tomcat8优化" class="headerlink" title="1、Tomcat8优化"></a>1、Tomcat8优化</h2><p>tomcat服务器在JavaEE项目中使用率非常高，所以在生产环境对tomcat的优化也变得非常重要了。</p>
<p>对于tomcat的优化，主要是从2个方面入手，一是，tomcat自身的配置，另一个是tomcat所运行的jvm虚拟机的调优。</p>
<p>下面我们将从这2个方面进行讲解。</p>
<h3 id="1-1、Tomcat配置优化"><a href="#1-1、Tomcat配置优化" class="headerlink" title="1.1、Tomcat配置优化"></a>1.1、Tomcat配置优化</h3><h4 id="1-1-1、部署安装tomcat8"><a href="#1-1-1、部署安装tomcat8" class="headerlink" title="1.1.1、部署安装tomcat8"></a>1.1.1、部署安装tomcat8</h4><p>下载并安装：</p>
<p><a href="https://tomcat.apache.org/download-80.cgi" target="_blank" rel="noopener">https://tomcat.apache.org/download-80.cgi</a></p>
<p> <img src="https://threadv.github.io/assets3/1537885756741.png" alt=""></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line">cd /tmp</span><br><span class="line">wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.34/bin/apache-tomcat-8.5.34.tar.gz</span><br><span class="line"></span><br><span class="line">tar -xvf apache-tomcat-8.5.34.tar.gz</span><br><span class="line">cd apache-tomcat-8.5.34/conf</span><br><span class="line"><span class="meta">#</span>修改配置文件，配置tomcat的管理用户</span><br><span class="line">vim tomcat-users.xml</span><br><span class="line"><span class="meta">#</span>写入如下内容：</span><br><span class="line">&lt;role rolename="manager"/&gt;</span><br><span class="line">&lt;role rolename="manager-gui"/&gt;</span><br><span class="line">&lt;role rolename="admin"/&gt;</span><br><span class="line">&lt;role rolename="admin-gui"/&gt;</span><br><span class="line">&lt;user username="tomcat" password="tomcat" roles="admin-gui,admin,manager-gui,manager"/&gt;</span><br><span class="line"><span class="meta">#</span>保存退出</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>如果是tomcat7，配置了tomcat用户就可以登录系统了，但是tomcat8中不行，还需要修改另一个配置文件，否则访问不了，提示403</span><br><span class="line">vim webapps/manager/META-INF/context.xml</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>将&lt;Valve的内容注释掉</span><br><span class="line">&lt;Context antiResourceLocking="false" privileged="true" &gt;</span><br><span class="line"> &lt;!-- &lt;Valve className="org.apache.catalina.valves.RemoteAddrValve"</span><br><span class="line">         allow="127\.\d+\.\d+\.\d+|::1|0:0:0:0:0:0:0:1" /&gt; --&gt;</span><br><span class="line">  &lt;Manager sessionAttributeValueClassNameFilter="java\.lang\.(?:Boolean|Integer|Long|Number|String)|org\.apache\.catalina\.filters\.CsrfPreventionFilter\$LruCache(?:\$1)?|java\.util\.(?:Linked)?HashMap"/&gt;</span><br><span class="line">&lt;/Context&gt;</span><br><span class="line"><span class="meta">#</span>保存退出即可</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>启动tomcat</span><br><span class="line">cd /tmp/apache-tomcat-8.5.34/bin/</span><br><span class="line">./startup.sh &amp;&amp; tail -f ../logs/catalina.out</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>打开浏览器进行测试访问</span><br><span class="line">http://192.168.40.133:8080/</span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1537886442880.png" alt="1537886442880"></p>
<p>点击“Server Status”，输入用户名、密码进行登录，tomcat/tomcat</p>
<p> <img src="https://threadv.github.io/assets3/1537886585179.png" alt="1537886585179"></p>
<p> <img src="https://threadv.github.io/assets3/1537886617256.png" alt="1537886617256"></p>
<p>进入之后即可看到服务的信息。</p>
<h4 id="1-1-2、禁用AJP连接"><a href="#1-1-2、禁用AJP连接" class="headerlink" title="1.1.2、禁用AJP连接"></a>1.1.2、禁用AJP连接</h4><p>在服务状态页面中可以看到，默认状态下会启用AJP服务，并且占用8009端口。</p>
<p> <img src="https://threadv.github.io/assets3/1537886721693.png" alt="1537886721693"></p>
<p>什么是AJP呢？</p>
<p>AJP（Apache JServer Protocol）<br>AJPv13协议是面向包的。WEB服务器和Servlet容器通过TCP连接来交互；为了节省SOCKET创建的昂贵代价，WEB服务器会尝试维护一个永久TCP连接到servlet容器，并且在多个请求和响应周期过程会重用连接。</p>
<p> <img src="https://threadv.github.io/assets3/1537886760361.png" alt="1537886760361"></p>
<p>我们一般是使用Nginx+tomcat的架构，所以用不着AJP协议，所以把AJP连接器禁用。</p>
<p>修改conf下的server.xml文件，将AJP服务禁用掉即可。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /&gt;</span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1537886904896.png" alt="1537886904896"></p>
<p>重启tomcat，查看效果。</p>
<p> <img src="https://threadv.github.io/assets3/1537887017961.png" alt="1537887017961"></p>
<p>可以看到AJP服务以及不存在了。</p>
<h4 id="1-1-3、执行器（线程池）"><a href="#1-1-3、执行器（线程池）" class="headerlink" title="1.1.3、执行器（线程池）"></a>1.1.3、执行器（线程池）</h4><p>在tomcat中每一个用户请求都是一个线程，所以可以使用线程池提高性能。</p>
<p>修改server.xml文件：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--将注释打开--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Executor</span> <span class="attr">name</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">namePrefix</span>=<span class="string">"catalina-exec-"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxThreads</span>=<span class="string">"500"</span> <span class="attr">minSpareThreads</span>=<span class="string">"50"</span> <span class="attr">prestartminSpareThreads</span>=<span class="string">"true"</span> <span class="attr">maxQueueSize</span>=<span class="string">"100"</span>/&gt;</span></span><br><span class="line"><span class="comment">&lt;!--</span></span><br><span class="line"><span class="comment">参数说明：</span></span><br><span class="line"><span class="comment">maxThreads：最大并发数，默认设置 200，一般建议在 500 ~ 1000，根据硬件设施和业务来判断</span></span><br><span class="line"><span class="comment">minSpareThreads：Tomcat 初始化时创建的线程数，默认设置 25</span></span><br><span class="line"><span class="comment">prestartminSpareThreads： 在 Tomcat 初始化的时候就初始化 minSpareThreads 的参数值，如果不等于 true，minSpareThreads 的值就没啥效果了</span></span><br><span class="line"><span class="comment">maxQueueSize，最大的等待队列数，超过则拒绝请求</span></span><br><span class="line"><span class="comment">--&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!--在Connector中设置executor属性指向上面的执行器--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Connector</span> <span class="attr">executor</span>=<span class="string">"tomcatThreadPool"</span>  <span class="attr">port</span>=<span class="string">"8080"</span> <span class="attr">protocol</span>=<span class="string">"HTTP/1.1"</span></span></span><br><span class="line"><span class="tag">               <span class="attr">connectionTimeout</span>=<span class="string">"20000"</span></span></span><br><span class="line"><span class="tag">               <span class="attr">redirectPort</span>=<span class="string">"8443"</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<p>保存退出，重启tomcat，查看效果。</p>
<p> <img src="https://threadv.github.io/assets3/1537891844779.png" alt="1537891844779"></p>
<p>在页面中显示最大线程数为-1，这个是正常的，仅仅是显示的问题，实际使用的指定的值。</p>
<p>也有人遇到这样的问题：<a href="https://blog.csdn.net/weixin_38278878/article/details/80144397" target="_blank" rel="noopener">https://blog.csdn.net/weixin_38278878/article/details/80144397</a></p>
<h4 id="1-1-4、3种运行模式"><a href="#1-1-4、3种运行模式" class="headerlink" title="1.1.4、3种运行模式"></a>1.1.4、3种运行模式</h4><p>tomcat的运行模式有3种：</p>
<ol>
<li>bio<br>默认的模式,性能非常低下,没有经过任何优化处理和支持.</li>
<li>nio<br>nio(new I/O)，是Java SE 1.4及后续版本提供的一种新的I/O操作方式(即java.nio包及其子包)。Java nio是一个基于缓冲区、并能提供非阻塞I/O操作的Java API，因此nio也被看成是non-blocking I/O的缩写。它拥有比传统I/O操作(bio)更好的并发运行性能。</li>
<li>apr<br>安装起来最困难,但是从操作系统级别来解决异步的IO问题,大幅度的提高性能.</li>
</ol>
<p>推荐使用nio，不过，在tomcat8中有最新的nio2，速度更快，建议使用nio2.</p>
<p>设置nio2：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Connector</span> <span class="attr">executor</span>=<span class="string">"tomcatThreadPool"</span>  <span class="attr">port</span>=<span class="string">"8080"</span> <span class="attr">protocol</span>=<span class="string">"org.apache.coyote.http11.Http11Nio2Protocol"</span></span></span><br><span class="line"><span class="tag">               <span class="attr">connectionTimeout</span>=<span class="string">"20000"</span></span></span><br><span class="line"><span class="tag">               <span class="attr">redirectPort</span>=<span class="string">"8443"</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1537892225489.png" alt="1537892225489"></p>
<p>可以看到已经设置为nio2了。</p>
<h3 id="1-2、部署测试用的java-web项目"><a href="#1-2、部署测试用的java-web项目" class="headerlink" title="1.2、部署测试用的java web项目"></a>1.2、部署测试用的java web项目</h3><p>为了方便测试性能，我们将部署一个java web项目，这个项目本身和本套课程没有什么关系，仅仅用于测试。</p>
<blockquote>
<p>注意：这里在测试时，我们使用一个新的tomcat，进行测试，后面再对其进行优化调整，再测试。</p>
</blockquote>
<h4 id="1-2-1、创建dashboard数据库"><a href="#1-2-1、创建dashboard数据库" class="headerlink" title="1.2.1、创建dashboard数据库"></a>1.2.1、创建dashboard数据库</h4><p>在资料中找到sql脚本文件dashboard.sql，在linux服务器上执行。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat dashboard.sql | mysql -uroot -proot</span><br></pre></td></tr></table></figure>
<p>创建完成后，可以看到有3张表。</p>
<p> <img src="https://threadv.github.io/assets3/1537892698827.png" alt="1537892698827"></p>
<h4 id="1-2-2、部署web应用"><a href="#1-2-2、部署web应用" class="headerlink" title="1.2.2、部署web应用"></a>1.2.2、部署web应用</h4><p>在资料中找到itcat-dashboard-web.war，上传到linux服务器，进行部署安装。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">cd /tmp/apache-tomcat-8.5.34/webapps</span><br><span class="line">rm -rf *</span><br><span class="line">mkdir ROOT</span><br><span class="line">cd ROOT/</span><br><span class="line"></span><br><span class="line">rz上传war包</span><br><span class="line">jar -xvf itcat-dashboard-web.war</span><br><span class="line">rm -rf itcat-dashboard-web.war</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>修改数据库配置文件</span><br><span class="line">cd /tmp/apache-tomcat-8.5.34/webapps/ROOT/WEB-INF/classes</span><br><span class="line">vim jdbc.properties</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>这里根据自己的实际情况进行配置</span><br><span class="line"></span><br><span class="line">jdbc.driverClassName=com.mysql.jdbc.Driver</span><br><span class="line">jdbc.url=jdbc:mysql://node01:3306/dashboard?useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true</span><br><span class="line">jdbc.username=root</span><br><span class="line">jdbc.password=root</span><br></pre></td></tr></table></figure>
<p>重新启动tomcat。</p>
<p>访问首页，查看是否已经启动成功：<a href="http://192.168.40.133:8080/index" target="_blank" rel="noopener">http://192.168.40.133:8080/index</a> <img src="https://threadv.github.io/assets3/1537946855605.png" alt="1537946855605"></p>
<h3 id="1-3、使用Apache-JMeter进行测试"><a href="#1-3、使用Apache-JMeter进行测试" class="headerlink" title="1.3、使用Apache JMeter进行测试"></a>1.3、使用Apache JMeter进行测试</h3><p>Apache Jmeter是开源的压力测试工具，我们借助于此工具进行测试，将测试出tomcat的吞吐量等信息。</p>
<h4 id="1-3-1、下载安装"><a href="#1-3-1、下载安装" class="headerlink" title="1.3.1、下载安装"></a>1.3.1、下载安装</h4><p>下载地址：<a href="http://jmeter.apache.org/download_jmeter.cgi" target="_blank" rel="noopener">http://jmeter.apache.org/download_jmeter.cgi</a></p>
<p> <img src="https://threadv.github.io/assets3/1537949454864.png" alt="1537949454864"></p>
<p>安装：直接将下载好的zip压缩包进行解压即可。</p>
<p> <img src="https://threadv.github.io/assets3/1537949516687.png" alt="1537949516687"></p>
<p>进入bin目录，找到jmeter.bat文件，双机打开即可启动。</p>
<p> <img src="https://threadv.github.io/assets3/1537949587540.png" alt="1537949587540"></p>
<p> <img src="https://threadv.github.io/assets3/1537949628061.png" alt="1537949628061"></p>
<p> <img src="https://threadv.github.io/assets3/1537949711256.png" alt="1537949711256"></p>
<h4 id="1-3-2、修改主题和语言"><a href="#1-3-2、修改主题和语言" class="headerlink" title="1.3.2、修改主题和语言"></a>1.3.2、修改主题和语言</h4><p>默认的主题是黑色风格的主题并且语言是英语，这样不太方便使用，所以需要修改下主题和中文语言。</p>
<p> <img src="https://threadv.github.io/assets3/1537949830874.png" alt="1537949830874"></p>
<p> <img src="https://threadv.github.io/assets3/1537949884794.png" alt="1537949884794"></p>
<p> <img src="https://threadv.github.io/assets3/1537949923207.png" alt="1537949923207"></p>
<p>主题修改完成。</p>
<p>接下来设置语言为简体中文。</p>
<p> <img src="https://threadv.github.io/assets3/1537949965832.png" alt="1537949965832"></p>
<p>语言修改完成。 <img src="https://threadv.github.io/assets3/1537950040975.png" alt="1537950040975"></p>
<h4 id="1-3-3、创建首页的测试用例"><a href="#1-3-3、创建首页的测试用例" class="headerlink" title="1.3.3、创建首页的测试用例"></a>1.3.3、创建首页的测试用例</h4><p>第一步：保存测试用例 <img src="https://threadv.github.io/assets3/1537952165502.png" alt="1537952165502"></p>
<p>第二步：添加线程组，使用线程模拟用户的并发</p>
<p> <img src="https://threadv.github.io/assets3/1537952849110.png" alt="1537952849110"></p>
<p> <img src="https://threadv.github.io/assets3/1537968506080.png" alt="1537968506080"></p>
<p>1000个线程，每个线程循环10次，也就是tomcat会接收到10000个请求。</p>
<p>第三步：添加http请求</p>
<p> <img src="https://threadv.github.io/assets3/1537970361030.png" alt="1537970361030"></p>
<p> <img src="https://threadv.github.io/assets3/1537970437128.png" alt="1537970437128"></p>
<p>第四步：添加请求监控</p>
<p> <img src="https://threadv.github.io/assets3/1537970530920.png" alt="1537970530920"></p>
<p> <img src="https://threadv.github.io/assets3/1537970575424.png" alt="1537970575424"></p>
<h4 id="1-3-4、启动、进行测试"><a href="#1-3-4、启动、进行测试" class="headerlink" title="1.3.4、启动、进行测试"></a>1.3.4、启动、进行测试</h4><p> <img src="https://threadv.github.io/assets3/1537970641386.png" alt="1537970641386"></p>
<h4 id="1-3-5、聚合报告"><a href="#1-3-5、聚合报告" class="headerlink" title="1.3.5、聚合报告"></a>1.3.5、聚合报告</h4><p>在聚合报告中，重点看吞吐量。</p>
<p> <img src="https://threadv.github.io/assets3/1538727715123.png" alt="1538727715123"></p>
<h3 id="1-4、调整tomcat参数进行优化"><a href="#1-4、调整tomcat参数进行优化" class="headerlink" title="1.4、调整tomcat参数进行优化"></a>1.4、调整tomcat参数进行优化</h3><p>通过上面测试可以看出，tomcat在不做任何调整时，吞吐量为73次/秒。</p>
<h4 id="1-4-1、禁用AJP服务"><a href="#1-4-1、禁用AJP服务" class="headerlink" title="1.4.1、禁用AJP服务"></a>1.4.1、禁用AJP服务</h4><p> <img src="https://threadv.github.io/assets3/1537971815919.png" alt="1537971815919"></p>
<p> <img src="https://threadv.github.io/assets3/1537971838198.png" alt="1537971838198"></p>
<p>可以看到，禁用AJP服务后，吞吐量会有所提升。</p>
<p>当然了，测试不一定准确，需要多测试几次才能看出是否有提升。</p>
<h4 id="1-4-2、设置线程池"><a href="#1-4-2、设置线程池" class="headerlink" title="1.4.2、设置线程池"></a>1.4.2、设置线程池</h4><p>通过设置线程池，调整线程池相关的参数进行测试tomcat的性能。</p>
<h5 id="1-4-2-1、最大线程数为500，初始为50"><a href="#1-4-2-1、最大线程数为500，初始为50" class="headerlink" title="1.4.2.1、最大线程数为500，初始为50"></a>1.4.2.1、最大线程数为500，初始为50</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Executor</span> <span class="attr">name</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">namePrefix</span>=<span class="string">"catalina-exec-"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxThreads</span>=<span class="string">"500"</span> <span class="attr">minSpareThreads</span>=<span class="string">"50"</span> <span class="attr">prestartminSpareThreads</span>=<span class="string">"true"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p>测试结果：</p>
<p> <img src="https://threadv.github.io/assets3/1538732278070.png" alt="1538732278070"></p>
<p>吞吐量为128次/秒，性能有所提升。</p>
<h5 id="1-4-2-2、最大线程数为1000，初始为200"><a href="#1-4-2-2、最大线程数为1000，初始为200" class="headerlink" title="1.4.2.2、最大线程数为1000，初始为200"></a>1.4.2.2、最大线程数为1000，初始为200</h5><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Executor</span> <span class="attr">name</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">namePrefix</span>=<span class="string">"catalina-exec-"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxThreads</span>=<span class="string">"1000"</span> <span class="attr">minSpareThreads</span>=<span class="string">"200"</span> <span class="attr">prestartminSpareThreads</span>=<span class="string">"true"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1538732664770.png" alt="1538732664770"></p>
<p>吞吐量为151，性能有所提升。</p>
<h5 id="1-4-2-3、最大线程数为5000，初始为1000"><a href="#1-4-2-3、最大线程数为5000，初始为1000" class="headerlink" title="1.4.2.3、最大线程数为5000，初始为1000"></a>1.4.2.3、最大线程数为5000，初始为1000</h5><p>是否是线程数最多，速度越快呢？ 我们来测试下。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Executor</span> <span class="attr">name</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">namePrefix</span>=<span class="string">"catalina-exec-"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxThreads</span>=<span class="string">"5000"</span> <span class="attr">minSpareThreads</span>=<span class="string">"1000"</span> <span class="attr">prestartminSpareThreads</span>=<span class="string">"true"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1538732998659.png" alt="1538732998659"></p>
<p>可以看到，虽然最大线程已经设置到5000，但是实际测试效果并不理想，并且平均的响应时间也边长了，所以单纯靠提升线程数量是不能一直得到性能提升的。</p>
<h5 id="1-4-2-4、设置最大等待队列数"><a href="#1-4-2-4、设置最大等待队列数" class="headerlink" title="1.4.2.4、设置最大等待队列数"></a>1.4.2.4、设置最大等待队列数</h5><p>默认情况下，请求发送到tomcat，如果tomcat正忙，那么该请求会一直等待。这样虽然可以保证每个请求都能请求到，但是请求时间就会边长。</p>
<p>有些时候，我们也不一定要求请求一定等待，可以设置最大等待队列大小，如果超过就不等待了。这样虽然有些请求是失败的，但是请求时间会虽短。典型的应用：12306。</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--最大等待数为100--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Executor</span> <span class="attr">name</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">namePrefix</span>=<span class="string">"catalina-exec-"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxThreads</span>=<span class="string">"500"</span> <span class="attr">minSpareThreads</span>=<span class="string">"100"</span> <span class="attr">prestartminSpareThreads</span>=<span class="string">"true"</span> <span class="attr">maxQueueSize</span>=<span class="string">"100"</span>/&gt;</span></span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1538733508872.png" alt="1538733508872"></p>
<p>测试结果：</p>
<ul>
<li>平均响应时间：3.1秒<ul>
<li>响应时间明显缩短</li>
</ul>
</li>
<li>错误率：49.88%<ul>
<li>错误率提升到一半，也可以理解，最大线程为500，测试的并发为1000</li>
</ul>
</li>
<li>吞吐量：238次/秒<ul>
<li>吞吐量明显提升</li>
</ul>
</li>
</ul>
<p>结论：响应时间、吞吐量这2个指标需要找到平衡才能达到更好的性能。</p>
<h4 id="1-4-3、设置nio2的运行模式"><a href="#1-4-3、设置nio2的运行模式" class="headerlink" title="1.4.3、设置nio2的运行模式"></a>1.4.3、设置nio2的运行模式</h4><p>将最大线程设置为500进行测试：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">Executor</span> <span class="attr">name</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">namePrefix</span>=<span class="string">"catalina-exec-"</span></span></span><br><span class="line"><span class="tag">        <span class="attr">maxThreads</span>=<span class="string">"500"</span> <span class="attr">minSpareThreads</span>=<span class="string">"50"</span> <span class="attr">prestartminSpareThreads</span>=<span class="string">"true"</span>/&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">&lt;!-- 设置nio2 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">Connector</span> <span class="attr">executor</span>=<span class="string">"tomcatThreadPool"</span> <span class="attr">port</span>=<span class="string">"8080"</span> <span class="attr">protocol</span>=<span class="string">"org.apache.coyote.http11.Http11Nio2Protocol"</span></span></span><br><span class="line"><span class="tag">               <span class="attr">connectionTimeout</span>=<span class="string">"20000"</span></span></span><br><span class="line"><span class="tag">               <span class="attr">redirectPort</span>=<span class="string">"8443"</span> /&gt;</span></span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets3/1538747028764.png" alt="1538747028764"></p>
<p>可以看到，平均响应时间有缩短，吞吐量有提升，可以得出结论：nio2的性能要高于nio。</p>
<h3 id="1-5、调整JVM参数进行优化"><a href="#1-5、调整JVM参数进行优化" class="headerlink" title="1.5、调整JVM参数进行优化"></a>1.5、调整JVM参数进行优化</h3><p>接下来，测试通过jvm参数进行优化，为了测试一致性，依然将最大线程数设置为500，启用nio2运行模式。</p>
<h4 id="1-5-1、设置并行垃圾回收器"><a href="#1-5-1、设置并行垃圾回收器" class="headerlink" title="1.5.1、设置并行垃圾回收器"></a>1.5.1、设置并行垃圾回收器</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>年轻代、老年代均使用并行收集器，初始堆内存64M，最大堆内存512M</span><br><span class="line">JAVA_OPTS="-XX:+UseParallelGC -XX:+UseParallelOldGC -Xms64m -Xmx512m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:../logs/gc.log"</span><br></pre></td></tr></table></figure>
<p><img src="https://threadv.github.io/assets3/1538012232502.png" alt="1538012232502"></p>
<p>测试结果与默认的JVM参数结果接近。（执行了2次测试，结果是第二次测试的结果）</p>
<h4 id="1-5-2、查看gc日志文件"><a href="#1-5-2、查看gc日志文件" class="headerlink" title="1.5.2、查看gc日志文件"></a>1.5.2、查看gc日志文件</h4><p>将gc.log文件上传到gceasy.io查看gc中是否存在问题。</p>
<p>问题一： <img src="https://threadv.github.io/assets3/1538012634194.png" alt="1538012634194"></p>
<p>在报告中显示，在5次GC时，系统所消耗的时间大于用户时间，这反应出的服务器的性能存在瓶颈，调度CPU等资源所消耗的时间要长一些。</p>
<p>问题二： <img src="https://threadv.github.io/assets3/1538013060119.png" alt="1538013060119"></p>
<p>可以关键指标中可以看出，吞吐量表现不错，但是gc时，线程的暂停时间稍有点长。</p>
<p>问题三： <img src="https://threadv.github.io/assets3/1538013925947.png" alt="1538013925947"></p>
<p>通过GC的统计可以看出：</p>
<ul>
<li>年轻代的gc有74次，次数稍有多，说明年轻代设置的大小不合适需要调整</li>
<li>FullGC有8次，说明堆内存的大小不合适，需要调整</li>
</ul>
<p>问题四： <img src="https://threadv.github.io/assets3/1538014237594.png" alt="1538014237594"></p>
<p>从GC原因的可以看出，年轻代大小设置不合理，导致了多次GC。</p>
<h4 id="1-5-3、调整年轻代大小"><a href="#1-5-3、调整年轻代大小" class="headerlink" title="1.5.3、调整年轻代大小"></a>1.5.3、调整年轻代大小</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JAVA_OPTS="-XX:+UseParallelGC -XX:+UseParallelOldGC -Xms128m -Xmx1024m -XX:NewSize=64m -XX:MaxNewSize=256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:../logs/gc.log"</span><br></pre></td></tr></table></figure>
<p>将初始堆大小设置为128m，最大为1024m</p>
<p>初始年轻代大小64m，年轻代最大256m <img src="https://threadv.github.io/assets3/1538015127822.png" alt="1538015127822"></p>
<p>从测试结果来看，吞吐量以及响应时间均有提升。</p>
<p>查看gc日志：</p>
<p> <img src="https://threadv.github.io/assets3/1538015681175.png" alt="1538015681175"></p>
<p> <img src="https://threadv.github.io/assets3/1538016117073.png" alt="1538016117073"></p>
<p>可以看到GC次数要明显减少，说明调整是有效的。</p>
<h4 id="1-5-4、设置G1垃圾回收器"><a href="#1-5-4、设置G1垃圾回收器" class="headerlink" title="1.5.4、设置G1垃圾回收器"></a>1.5.4、设置G1垃圾回收器</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>设置了最大停顿时间100毫秒，初始堆内存128m，最大堆内存1024m</span><br><span class="line">JAVA_OPTS="-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xms128m -Xmx1024m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:../logs/gc.log"</span><br></pre></td></tr></table></figure>
<p>测试结果：  <img src="https://threadv.github.io/assets3/1538019510782.png" alt="1538019510782"></p>
<p><img src="https://threadv.github.io/assets3/1538019458636.png" alt="1538019458636"></p>
<p>可以看到，吞吐量有所提升，评价响应时间也有所缩短。</p>
<h4 id="1-5-5、小结"><a href="#1-5-5、小结" class="headerlink" title="1.5.5、小结"></a>1.5.5、小结</h4><p>通过上述的测试，可以总结出，对tomcat性能优化就是需要不断的进行调整参数，然后测试结果，可能会调优也可能会调差，这时就需要借助于gc的可视化工具来看gc的情况。再帮我我们做出决策应该调整哪些参数。</p>
<h2 id="2、JVM字节码"><a href="#2、JVM字节码" class="headerlink" title="2、JVM字节码"></a>2、JVM字节码</h2><p>前面我们通过tomcat本身的参数以及jvm的参数对tomcat做了优化，其实要想将应用程序跑的更快、效率更高，除了对tomcat容器以及jvm优化外，应用程序代码本身如果写的效率不高的，那么也是不行的，所以，对于程序本身的优化也就很重要了。</p>
<p>对于程序本身的优化，可以借鉴很多前辈们的经验，但是有些时候，在从源码角度方面分析的话，不好鉴别出哪个效率高，如对字符串拼接的操作，是直接“+”号拼接效率高还是使用StringBuilder效率高？</p>
<p>这个时候，就需要通过查看编译好的class文件中字节码，就可以找到答案。</p>
<p>我们都知道，java编写应用，需要先通过javac命令编译成class文件，再通过jvm执行，jvm执行时是需要将class文件中的字节码载入到jvm进行运行的。</p>
<h3 id="2-1、通过javap命令查看class文件的字节码内容"><a href="#2-1、通过javap命令查看class文件的字节码内容" class="headerlink" title="2.1、通过javap命令查看class文件的字节码内容"></a>2.1、通过javap命令查看class文件的字节码内容</h3><p>首先，看一个简单的Test1类的代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.test.jvm;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test1</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> a = <span class="number">2</span>;</span><br><span class="line">        <span class="keyword">int</span> b = <span class="number">5</span>;</span><br><span class="line">        <span class="keyword">int</span> c = b - a;</span><br><span class="line">        System.out.println(c);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>通过javap命令查看class文件中的字节码内容：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">javap -v Test1.class &gt; Test1.txt</span><br><span class="line"></span><br><span class="line">javap用法: javap &lt;options&gt; &lt;classes&gt;</span><br><span class="line">其中, 可能的选项包括:</span><br><span class="line">  -help  --help  -?        输出此用法消息</span><br><span class="line">  -version                 版本信息</span><br><span class="line">  -v  -verbose             输出附加信息</span><br><span class="line">  -l                       输出行号和本地变量表</span><br><span class="line">  -public                  仅显示公共类和成员</span><br><span class="line">  -protected               显示受保护的/公共类和成员</span><br><span class="line">  -package                 显示程序包/受保护的/公共类</span><br><span class="line">                           和成员 (默认)</span><br><span class="line">  -p  -private             显示所有类和成员</span><br><span class="line">  -c                       对代码进行反汇编</span><br><span class="line">  -s                       输出内部类型签名</span><br><span class="line">  -sysinfo                 显示正在处理的类的</span><br><span class="line">                           系统信息 (路径, 大小, 日期, MD5 散列)</span><br><span class="line">  -constants               显示最终常量</span><br><span class="line">  -classpath &lt;path&gt;        指定查找用户类文件的位置</span><br><span class="line">  -cp &lt;path&gt;               指定查找用户类文件的位置</span><br><span class="line">  -bootclasspath &lt;path&gt;    覆盖引导类文件的位置</span><br></pre></td></tr></table></figure>
<p>查看Test1.txt文件，内容如下：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br></pre></td><td class="code"><pre><span class="line">Classfile /F:/code/test-jvm/test-jvm-test/target/classes/cn/test/jvm/Test1.class</span><br><span class="line">  Last modified <span class="number">2018</span>-<span class="number">9</span>-<span class="number">27</span>; size <span class="number">577</span> bytes</span><br><span class="line">  MD5 checksum <span class="number">4214859</span>db3543c0c783ec8a216a4795f</span><br><span class="line">  Compiled from <span class="string">"Test1.java"</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">cn</span>.<span class="title">test</span>.<span class="title">jvm</span>.<span class="title">Test1</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: ACC_PUBLIC, ACC_SUPER</span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #5.#23         // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Fieldref           #24.#25        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">   #3 = Methodref          #26.#27        // java/io/PrintStream.println:(I)V</span><br><span class="line">   #4 = Class              #28            // cn/test/jvm/Test1</span><br><span class="line">   #5 = Class              #29            // java/lang/Object</span><br><span class="line">   #6 = Utf8               &lt;init&gt;</span><br><span class="line">   #7 = Utf8               ()V</span><br><span class="line">   #8 = Utf8               Code</span><br><span class="line">   #9 = Utf8               LineNumberTable</span><br><span class="line">  #10 = Utf8               LocalVariableTable</span><br><span class="line">  #11 = Utf8               this</span><br><span class="line">  #12 = Utf8               Lcn/test/jvm/Test1;</span><br><span class="line">  #13 = Utf8               main</span><br><span class="line">  #14 = Utf8               ([Ljava/lang/String;)V</span><br><span class="line">  #15 = Utf8               args</span><br><span class="line">  #16 = Utf8               [Ljava/lang/String;</span><br><span class="line">  #17 = Utf8               a</span><br><span class="line">  #18 = Utf8               I</span><br><span class="line">  #19 = Utf8               b</span><br><span class="line">  #20 = Utf8               c</span><br><span class="line">  #21 = Utf8               SourceFile</span><br><span class="line">  #22 = Utf8               Test1.java</span><br><span class="line">  #23 = NameAndType        #6:#7          // "&lt;init&gt;":()V</span><br><span class="line">  #24 = Class              #30            // java/lang/System</span><br><span class="line">  #25 = NameAndType        #31:#32        // out:Ljava/io/PrintStream;</span><br><span class="line">  #26 = Class              #33            // java/io/PrintStream</span><br><span class="line">  #27 = NameAndType        #34:#35        // println:(I)V</span><br><span class="line">  #28 = Utf8               cn/test/jvm/Test1</span><br><span class="line">  #29 = Utf8               java/lang/Object</span><br><span class="line">  #30 = Utf8               java/lang/System</span><br><span class="line">  #31 = Utf8               out</span><br><span class="line">  #32 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #33 = Utf8               java/io/PrintStream</span><br><span class="line">  #34 = Utf8               println</span><br><span class="line">  #35 = Utf8               (I)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> cn.test.jvm.Test1();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">3</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test1;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(java.lang.String[])</span></span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">4</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: iconst_2</span><br><span class="line">         <span class="number">1</span>: istore_1</span><br><span class="line">         <span class="number">2</span>: iconst_5</span><br><span class="line">         <span class="number">3</span>: istore_2</span><br><span class="line">         <span class="number">4</span>: iload_2</span><br><span class="line">         <span class="number">5</span>: iload_1</span><br><span class="line">         <span class="number">6</span>: isub</span><br><span class="line">         <span class="number">7</span>: istore_3</span><br><span class="line">         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">11</span>: iload_3</span><br><span class="line">        12: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line">        <span class="number">15</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">6</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">7</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">8</span>: <span class="number">4</span></span><br><span class="line">        line <span class="number">9</span>: <span class="number">8</span></span><br><span class="line">        line <span class="number">10</span>: <span class="number">15</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">16</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line">            <span class="number">2</span>      <span class="number">14</span>     <span class="number">1</span>     a   I</span><br><span class="line">            <span class="number">4</span>      <span class="number">12</span>     <span class="number">2</span>     b   I</span><br><span class="line">            <span class="number">8</span>       <span class="number">8</span>     <span class="number">3</span>     c   I</span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"Test1.java"</span></span><br></pre></td></tr></table></figure>
<p>内容大致分为4个部分：</p>
<p>第一部分：显示了生成这个class的java源文件、版本信息、生成时间等。</p>
<p>第二部分：显示了该类中所涉及到常量池，共35个常量。</p>
<p>第三部分：显示该类的构造器，编译器自动插入的。</p>
<p>第四部分：显示了main方的信息。（这个是需要我们重点关注的）</p>
<h3 id="2-2、常量池"><a href="#2-2、常量池" class="headerlink" title="2.2、常量池"></a>2.2、常量池</h3><p>官网文档：</p>
<p><a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4-140" target="_blank" rel="noopener">https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.4-140</a></p>
<table>
<thead>
<tr>
<th>Constant Type</th>
<th>Value</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CONSTANT_Class</code></td>
<td>7</td>
<td>类或接口的符号引用</td>
</tr>
<tr>
<td><code>CONSTANT_Fieldref</code></td>
<td>9</td>
<td>字段的符号引用</td>
</tr>
<tr>
<td><code>CONSTANT_Methodref</code></td>
<td>10</td>
<td>类中方法的符号引用</td>
</tr>
<tr>
<td><code>CONSTANT_InterfaceMethodref</code></td>
<td>11</td>
<td>接口中方法的符号引用</td>
</tr>
<tr>
<td><code>CONSTANT_String</code></td>
<td>8</td>
<td>字符串类型常量</td>
</tr>
<tr>
<td><code>CONSTANT_Integer</code></td>
<td>3</td>
<td>整形常量</td>
</tr>
<tr>
<td><code>CONSTANT_Float</code></td>
<td>4</td>
<td>浮点型常量</td>
</tr>
<tr>
<td><code>CONSTANT_Long</code></td>
<td>5</td>
<td>长整型常量</td>
</tr>
<tr>
<td><code>CONSTANT_Double</code></td>
<td>6</td>
<td>双精度浮点型常量</td>
</tr>
<tr>
<td><code>CONSTANT_NameAndType</code></td>
<td>12</td>
<td>字段或方法的符号引用</td>
</tr>
<tr>
<td><code>CONSTANT_Utf8</code></td>
<td>1</td>
<td>UTF-8编码的字符串</td>
</tr>
<tr>
<td><code>CONSTANT_MethodHandle</code></td>
<td>15</td>
<td>表示方法句柄</td>
</tr>
<tr>
<td><code>CONSTANT_MethodType</code></td>
<td>16</td>
<td>标志方法类型</td>
</tr>
<tr>
<td><code>CONSTANT_InvokeDynamic</code></td>
<td>18</td>
<td>表示一个动态方法调用点</td>
</tr>
</tbody>
</table>
<h3 id="2-3、描述符"><a href="#2-3、描述符" class="headerlink" title="2.3、描述符"></a>2.3、描述符</h3><h4 id="2-3-1、字段描述符"><a href="#2-3-1、字段描述符" class="headerlink" title="2.3.1、字段描述符"></a>2.3.1、字段描述符</h4><p>官网：<a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2" target="_blank" rel="noopener">https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.2</a></p>
<table>
<thead>
<tr>
<th><em>FieldType</em> term</th>
<th>Type</th>
<th>Interpretation</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>B</code></td>
<td><code>byte</code></td>
<td>signed byte</td>
</tr>
<tr>
<td><code>C</code></td>
<td><code>char</code></td>
<td>Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16</td>
</tr>
<tr>
<td><code>D</code></td>
<td><code>double</code></td>
<td>double-precision floating-point value</td>
</tr>
<tr>
<td><code>F</code></td>
<td><code>float</code></td>
<td>single-precision floating-point value</td>
</tr>
<tr>
<td><code>I</code></td>
<td><code>int</code></td>
<td>integer</td>
</tr>
<tr>
<td><code>J</code></td>
<td><code>long</code></td>
<td>long integer</td>
</tr>
<tr>
<td><code>LClassName;</code></td>
<td><code>reference</code></td>
<td>an instance of class <em>ClassName</em></td>
</tr>
<tr>
<td><code>S</code></td>
<td><code>short</code></td>
<td>signed short</td>
</tr>
<tr>
<td><code>Z</code></td>
<td><code>boolean</code></td>
<td><code>true</code> or <code>false</code></td>
</tr>
<tr>
<td><code>[</code></td>
<td><code>reference</code></td>
<td>one array dimension</td>
</tr>
</tbody>
</table>
<h4 id="2-3-2、方法描述符"><a href="#2-3-2、方法描述符" class="headerlink" title="2.3.2、方法描述符"></a>2.3.2、方法描述符</h4><p>官网：<a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.3" target="_blank" rel="noopener">https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.3.3</a></p>
<p>示例：</p>
<p>The method descriptor for the method:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function">Object <span class="title">m</span><span class="params">(<span class="keyword">int</span> i, <span class="keyword">double</span> d, Thread t)</span> </span>&#123;...&#125;</span><br></pre></td></tr></table></figure>
<p>is:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(IDLjava/lang/Thread;)Ljava/lang/Object;</span><br></pre></td></tr></table></figure>
<h3 id="2-4、解读方法字节码"><a href="#2-4、解读方法字节码" class="headerlink" title="2.4、解读方法字节码"></a>2.4、解读方法字节码</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(java.lang.String[])</span></span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V  <span class="comment">//方法描述，V表示该方法的放回值为void</span></span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC  <span class="comment">// 方法修饰符，public、static的</span></span><br><span class="line">    Code:</span><br><span class="line">      <span class="comment">// stack=2,操作栈的大小为2、locals=4，本地变量表大小，args_size=1, 参数的个数</span></span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">4</span>, args_size=<span class="number">1</span> </span><br><span class="line">         <span class="number">0</span>: iconst_2  <span class="comment">//将数字2值压入操作栈，位于栈的最上面</span></span><br><span class="line">         <span class="number">1</span>: istore_1  <span class="comment">//从操作栈中弹出一个元素(数字2)，放入到本地变量表中，位于下标为1的位置（下标为0的是this）</span></span><br><span class="line">         <span class="number">2</span>: iconst_5  <span class="comment">//将数字5值压入操作栈，位于栈的最上面</span></span><br><span class="line">         <span class="number">3</span>: istore_2  <span class="comment">//从操作栈中弹出一个元素(5)，放入到本地变量表中，位于第下标为2个位置</span></span><br><span class="line">         <span class="number">4</span>: iload_2  <span class="comment">//将本地变量表中下标为2的位置元素压入操作栈（5）</span></span><br><span class="line">         <span class="number">5</span>: iload_1  <span class="comment">//将本地变量表中下标为1的位置元素压入操作栈（2）</span></span><br><span class="line">         <span class="number">6</span>: isub  <span class="comment">//操作栈中的2个数字相减</span></span><br><span class="line">         <span class="number">7</span>: istore_3 <span class="comment">// 将相减的结果压入到本地本地变量表中，位于下标为3的位置</span></span><br><span class="line">         <span class="comment">// 通过#2号找到对应的常量，即可找到对应的引用       </span></span><br><span class="line">         8: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">11</span>: iload_3 <span class="comment">//将本地变量表中下标为3的位置元素压入操作栈（3）</span></span><br><span class="line">        <span class="comment">// 通过#3号找到对应的常量，即可找到对应的引用，进行方法调用</span></span><br><span class="line">        12: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line">        <span class="number">15</span>: <span class="keyword">return</span> <span class="comment">//返回</span></span><br><span class="line">      LineNumberTable:  <span class="comment">//行号的列表</span></span><br><span class="line">        line <span class="number">6</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">7</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">8</span>: <span class="number">4</span></span><br><span class="line">        line <span class="number">9</span>: <span class="number">8</span></span><br><span class="line">        line <span class="number">10</span>: <span class="number">15</span></span><br><span class="line">      LocalVariableTable: <span class="comment">// 本地变量表</span></span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">16</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line">            <span class="number">2</span>      <span class="number">14</span>     <span class="number">1</span>     a   I</span><br><span class="line">            <span class="number">4</span>      <span class="number">12</span>     <span class="number">2</span>     b   I</span><br><span class="line">            <span class="number">8</span>       <span class="number">8</span>     <span class="number">3</span>     c   I</span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"Test1.java"</span></span><br></pre></td></tr></table></figure>
<h4 id="2-4-1、图解"><a href="#2-4-1、图解" class="headerlink" title="2.4.1、图解"></a>2.4.1、图解</h4><p> <img src="https://threadv.github.io/assets3/1538065414765.png" alt="1538065414765"></p>
<p> <img src="https://threadv.github.io/assets3/1538065819308.png" alt="1538065819308"></p>
<p> <img src="https://threadv.github.io/assets3/1538066431935.png" alt="1538066431935"></p>
<h3 id="2-5、研究-i-与-i-的不同"><a href="#2-5、研究-i-与-i-的不同" class="headerlink" title="2.5、研究 i++ 与 ++i 的不同"></a>2.5、研究 i++ 与 ++i 的不同</h3><p>我们都知道，i++表示，先返回再+1，++i表示，先+1再返回。它的底层是怎么样的呢? 我们一起探究下。</p>
<p>编写测试代码：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test2</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Test2().method1();</span><br><span class="line">        <span class="keyword">new</span> Test2().method2();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">method1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">int</span> a = i++;</span><br><span class="line">        System.out.println(a); <span class="comment">//打印1</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">method2</span><span class="params">()</span></span>&#123;</span><br><span class="line">        <span class="keyword">int</span> i = <span class="number">1</span>;</span><br><span class="line">        <span class="keyword">int</span> a = ++i;</span><br><span class="line">        System.out.println(a);<span class="comment">//打印2</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="2-5-1、查看class字节码"><a href="#2-5-1、查看class字节码" class="headerlink" title="2.5.1、查看class字节码"></a>2.5.1、查看class字节码</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br></pre></td><td class="code"><pre><span class="line">Classfile /F:/code/test-jvm/test-jvm-test/target/classes/cn/test/jvm/Test2.class</span><br><span class="line">  MD5 checksum <span class="number">901660f</span>c11c43b6daadd0942150960ed</span><br><span class="line">  Compiled from <span class="string">"Test2.java"</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">cn</span>.<span class="title">test</span>.<span class="title">jvm</span>.<span class="title">Test2</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: ACC_PUBLIC, ACC_SUPER</span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #8.#27         // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Class              #28            // cn/test/jvm/Test2</span><br><span class="line">   #3 = Methodref          #2.#27         // cn/test/jvm/Test2."&lt;init&gt;":()V</span><br><span class="line">   #4 = Methodref          #2.#29         // cn/test/jvm/Test2.method1:()V</span><br><span class="line">   #5 = Methodref          #2.#30         // cn/test/jvm/Test2.method2:()V</span><br><span class="line">   #6 = Fieldref           #31.#32        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">   #7 = Methodref          #33.#34        // java/io/PrintStream.println:(I)V</span><br><span class="line">   #8 = Class              #35            // java/lang/Object</span><br><span class="line">   #9 = Utf8               &lt;init&gt;</span><br><span class="line">  #10 = Utf8               ()V</span><br><span class="line">  #11 = Utf8               Code</span><br><span class="line">  #12 = Utf8               LineNumberTable</span><br><span class="line">  #13 = Utf8               LocalVariableTable</span><br><span class="line">  #14 = Utf8               this</span><br><span class="line">  #15 = Utf8               Lcn/test/jvm/Test2;</span><br><span class="line">  #16 = Utf8               main</span><br><span class="line">  #17 = Utf8               ([Ljava/lang/String;)V</span><br><span class="line">  #18 = Utf8               args</span><br><span class="line">  #19 = Utf8               [Ljava/lang/String;</span><br><span class="line">  #20 = Utf8               method1</span><br><span class="line">  #21 = Utf8               i</span><br><span class="line">  #22 = Utf8               I</span><br><span class="line">  #23 = Utf8               a</span><br><span class="line">  #24 = Utf8               method2</span><br><span class="line">  #25 = Utf8               SourceFile</span><br><span class="line">  #26 = Utf8               Test2.java</span><br><span class="line">  #27 = NameAndType        #9:#10         // "&lt;init&gt;":()V</span><br><span class="line">  #28 = Utf8               cn/test/jvm/Test2</span><br><span class="line">  #29 = NameAndType        #20:#10        // method1:()V</span><br><span class="line">  #30 = NameAndType        #24:#10        // method2:()V</span><br><span class="line">  #31 = Class              #36            // java/lang/System</span><br><span class="line">  #32 = NameAndType        #37:#38        // out:Ljava/io/PrintStream;</span><br><span class="line">  #33 = Class              #39            // java/io/PrintStream</span><br><span class="line">  #34 = NameAndType        #40:#41        // println:(I)V</span><br><span class="line">  #35 = Utf8               java/lang/Object</span><br><span class="line">  #36 = Utf8               java/lang/System</span><br><span class="line">  #37 = Utf8               out</span><br><span class="line">  #38 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #39 = Utf8               java/io/PrintStream</span><br><span class="line">  #40 = Utf8               println</span><br><span class="line">  #41 = Utf8               (I)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> cn.test.jvm.Test2();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">3</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test2;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(java.lang.String[])</span></span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: new           #2                  // class cn/test/jvm/Test2</span><br><span class="line">         <span class="number">3</span>: dup</span><br><span class="line">         4: invokespecial #3                  // Method "&lt;init&gt;":()V</span><br><span class="line">         7: invokevirtual #4                  // Method method1:()V</span><br><span class="line">        10: new           #2                  // class cn/test/jvm/Test2</span><br><span class="line">        <span class="number">13</span>: dup</span><br><span class="line">        14: invokespecial #3                  // Method "&lt;init&gt;":()V</span><br><span class="line">        17: invokevirtual #5                  // Method method2:()V</span><br><span class="line">        <span class="number">20</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">6</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">7</span>: <span class="number">10</span></span><br><span class="line">        line <span class="number">8</span>: <span class="number">20</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">21</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">method1</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">3</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: iconst_1</span><br><span class="line">         <span class="number">1</span>: istore_1</span><br><span class="line">         <span class="number">2</span>: iload_1</span><br><span class="line">         <span class="number">3</span>: iinc          <span class="number">1</span>, <span class="number">1</span></span><br><span class="line">         <span class="number">6</span>: istore_2</span><br><span class="line">         7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">10</span>: iload_2</span><br><span class="line">        11: invokevirtual #7                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line">        <span class="number">14</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">11</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">13</span>: <span class="number">7</span></span><br><span class="line">        line <span class="number">14</span>: <span class="number">14</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">15</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test2;</span><br><span class="line">            <span class="number">2</span>      <span class="number">13</span>     <span class="number">1</span>     i   I</span><br><span class="line">            <span class="number">7</span>       <span class="number">8</span>     <span class="number">2</span>     a   I</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">method2</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">3</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: iconst_1</span><br><span class="line">         <span class="number">1</span>: istore_1</span><br><span class="line">         <span class="number">2</span>: iinc          <span class="number">1</span>, <span class="number">1</span></span><br><span class="line">         <span class="number">5</span>: iload_1</span><br><span class="line">         <span class="number">6</span>: istore_2</span><br><span class="line">         7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">10</span>: iload_2</span><br><span class="line">        11: invokevirtual #7                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line">        <span class="number">14</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">17</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">18</span>: <span class="number">2</span></span><br><span class="line">        line <span class="number">19</span>: <span class="number">7</span></span><br><span class="line">        line <span class="number">20</span>: <span class="number">14</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">15</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test2;</span><br><span class="line">            <span class="number">2</span>      <span class="number">13</span>     <span class="number">1</span>     i   I</span><br><span class="line">            <span class="number">7</span>       <span class="number">8</span>     <span class="number">2</span>     a   I</span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"Test2.java"</span></span><br></pre></td></tr></table></figure>
<h4 id="2-5-2、对比"><a href="#2-5-2、对比" class="headerlink" title="2.5.2、对比"></a>2.5.2、对比</h4><p>i++：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> <span class="number">0</span>: iconst_1  <span class="comment">//将数字1压入到操作栈</span></span><br><span class="line"> <span class="number">1</span>: istore_1  <span class="comment">//将数字1从操作栈弹出，压入到本地变量表中，下标为1</span></span><br><span class="line"> <span class="number">2</span>: iload_1   <span class="comment">//从本地变量表中获取下标为1的数据，压入到操作栈中</span></span><br><span class="line"> <span class="number">3</span>: iinc          <span class="number">1</span>, <span class="number">1</span> <span class="comment">// 将本地变量中的1，再+1</span></span><br><span class="line"> <span class="number">6</span>: istore_2  <span class="comment">// 将数字1从操作栈弹出，压入到本地变量表中，下标为2</span></span><br><span class="line"> 7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line"><span class="number">10</span>: iload_2   <span class="comment">//从本地变量表中获取下标为2的数据，压入到操作栈中</span></span><br><span class="line">11: invokevirtual #7                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line"><span class="number">14</span>: <span class="keyword">return</span></span><br></pre></td></tr></table></figure>
<p>++i：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"> <span class="number">0</span>: iconst_1  <span class="comment">//将数字1压入到操作栈</span></span><br><span class="line"> <span class="number">1</span>: istore_1  <span class="comment">//将数字1从操作栈弹出，压入到本地变量表中，下标为1</span></span><br><span class="line"> <span class="number">2</span>: iinc          <span class="number">1</span>, <span class="number">1</span><span class="comment">// 将本地变量中的1，再+1</span></span><br><span class="line"> <span class="number">5</span>: iload_1  <span class="comment">//从本地变量表中获取下标为1的数据（2），压入到操作栈中</span></span><br><span class="line"> <span class="number">6</span>: istore_2 <span class="comment">//将数字2从操作栈弹出，压入到本地变量表中，下标为2</span></span><br><span class="line"> 7: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line"><span class="number">10</span>: iload_2 <span class="comment">//从本地变量表中获取下标为2的数据（2），压入到操作栈中</span></span><br><span class="line">11: invokevirtual #7                  // Method java/io/PrintStream.println:(I)V</span><br><span class="line"><span class="number">14</span>: <span class="keyword">return</span></span><br></pre></td></tr></table></figure>
<p>区别：</p>
<ul>
<li>i++<ul>
<li>只是在本地变量中对数字做了相加，并没有将数据压入到操作栈</li>
<li>将前面拿到的数字1，再次从操作栈中拿到，压入到本地变量中</li>
</ul>
</li>
<li>++i<ul>
<li>将本地变量中的数字做了相加，并且将数据压入到操作栈</li>
<li>将操作栈中的数据，再次压入到本地变量中</li>
</ul>
</li>
</ul>
<p>小结：可以通过查看字节码的方式对代码的底层做研究，探究其原理。</p>
<h3 id="2-6、字符串拼接"><a href="#2-6、字符串拼接" class="headerlink" title="2.6、字符串拼接"></a>2.6、字符串拼接</h3><p>字符串的拼接在开发过程中使用是非常频繁的，常用的方式有三种：</p>
<ul>
<li>+号拼接： str+”456”</li>
<li>StringBuilder拼接</li>
<li>StringBuffer拼接</li>
</ul>
<p>StringBuffer是保证线程安全的，效率是比较低的，我们更多的是使用场景是不会涉及到线程安全的问题的，所以更多的时候会选择StringBuilder，效率会高一些。</p>
<p>那么，问题来了，StringBuilder和“+”号拼接，哪个效率高呢？接下来我们通过字节码的方式进行探究。</p>
<p>首先，编写个示例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.test.jvm;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test3</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Test3().m1();</span><br><span class="line">        <span class="keyword">new</span> Test3().m2();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        String s1 = <span class="string">"123"</span>;</span><br><span class="line">        String s2 = <span class="string">"456"</span>;</span><br><span class="line">        String s3 = s1 + s2;</span><br><span class="line">        System.out.println(s3);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m2</span><span class="params">()</span></span>&#123;</span><br><span class="line">        String s1 = <span class="string">"123"</span>;</span><br><span class="line">        String s2 = <span class="string">"456"</span>;</span><br><span class="line">        StringBuilder sb = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">        sb.append(s1);</span><br><span class="line">        sb.append(s2);</span><br><span class="line">        String s3 = sb.toString();</span><br><span class="line">        System.out.println(s3);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>查看Test3.class的字节码</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br></pre></td><td class="code"><pre><span class="line">Classfile /F:/code/test-jvm/test-jvm-test/target/classes/cn/test/jvm/Test3.class</span><br><span class="line">  MD5 checksum b3f7629e7e37768b9b5581be01df40d6</span><br><span class="line">  Compiled from <span class="string">"Test3.java"</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">cn</span>.<span class="title">test</span>.<span class="title">jvm</span>.<span class="title">Test3</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: ACC_PUBLIC, ACC_SUPER</span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #14.#36        // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Class              #37            // cn/test/jvm/Test3</span><br><span class="line">   #3 = Methodref          #2.#36         // cn/test/jvm/Test3."&lt;init&gt;":()V</span><br><span class="line">   #4 = Methodref          #2.#38         // cn/test/jvm/Test3.m1:()V</span><br><span class="line">   #5 = Methodref          #2.#39         // cn/test/jvm/Test3.m2:()V</span><br><span class="line">   #6 = String             #40            // 123</span><br><span class="line">   #7 = String             #41            // 456</span><br><span class="line">   #8 = Class              #42            // java/lang/StringBuilder</span><br><span class="line">   #9 = Methodref          #8.#36         // java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">  #10 = Methodref          #8.#43         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #11 = Methodref          #8.#44         // java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">  #12 = Fieldref           #45.#46        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">  #13 = Methodref          #47.#48        // java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">  #14 = Class              #49            // java/lang/Object</span><br><span class="line">  #15 = Utf8               &lt;init&gt;</span><br><span class="line">  #16 = Utf8               ()V</span><br><span class="line">  #17 = Utf8               Code</span><br><span class="line">  #18 = Utf8               LineNumberTable</span><br><span class="line">  #19 = Utf8               LocalVariableTable</span><br><span class="line">  #20 = Utf8               this</span><br><span class="line">  #21 = Utf8               Lcn/test/jvm/Test3;</span><br><span class="line">  #22 = Utf8               main</span><br><span class="line">  #23 = Utf8               ([Ljava/lang/String;)V</span><br><span class="line">  #24 = Utf8               args</span><br><span class="line">  #25 = Utf8               [Ljava/lang/String;</span><br><span class="line">  #26 = Utf8               m1</span><br><span class="line">  #27 = Utf8               s1</span><br><span class="line">  #28 = Utf8               Ljava/lang/String;</span><br><span class="line">  #29 = Utf8               s2</span><br><span class="line">  #30 = Utf8               s3</span><br><span class="line">  #31 = Utf8               m2</span><br><span class="line">  #32 = Utf8               sb</span><br><span class="line">  #33 = Utf8               Ljava/lang/StringBuilder;</span><br><span class="line">  #34 = Utf8               SourceFile</span><br><span class="line">  #35 = Utf8               Test3.java</span><br><span class="line">  #36 = NameAndType        #15:#16        // "&lt;init&gt;":()V</span><br><span class="line">  #37 = Utf8               cn/test/jvm/Test3</span><br><span class="line">  #38 = NameAndType        #26:#16        // m1:()V</span><br><span class="line">  #39 = NameAndType        #31:#16        // m2:()V</span><br><span class="line">  #40 = Utf8               123</span><br><span class="line">  #41 = Utf8               456</span><br><span class="line">  #42 = Utf8               java/lang/StringBuilder</span><br><span class="line">  #43 = NameAndType        #50:#51        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #44 = NameAndType        #52:#53        // toString:()Ljava/lang/String;</span><br><span class="line">  #45 = Class              #54            // java/lang/System</span><br><span class="line">  #46 = NameAndType        #55:#56        // out:Ljava/io/PrintStream;</span><br><span class="line">  #47 = Class              #57            // java/io/PrintStream</span><br><span class="line">  #48 = NameAndType        #58:#59        // println:(Ljava/lang/String;)V</span><br><span class="line">  #49 = Utf8               java/lang/Object</span><br><span class="line">  #50 = Utf8               append</span><br><span class="line">  #51 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #52 = Utf8               toString</span><br><span class="line">  #53 = Utf8               ()Ljava/lang/String;</span><br><span class="line">  #54 = Utf8               java/lang/System</span><br><span class="line">  #55 = Utf8               out</span><br><span class="line">  #56 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #57 = Utf8               java/io/PrintStream</span><br><span class="line">  #58 = Utf8               println</span><br><span class="line">  #59 = Utf8               (Ljava/lang/String;)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> cn.test.jvm.Test3();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">3</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test3;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(java.lang.String[])</span></span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: new           #2                  // class cn/test/jvm/Test3</span><br><span class="line">         <span class="number">3</span>: dup</span><br><span class="line">         4: invokespecial #3                  // Method "&lt;init&gt;":()V</span><br><span class="line">         7: invokevirtual #4                  // Method m1:()V</span><br><span class="line">        10: new           #2                  // class cn/test/jvm/Test3</span><br><span class="line">        <span class="number">13</span>: dup</span><br><span class="line">        14: invokespecial #3                  // Method "&lt;init&gt;":()V</span><br><span class="line">        17: invokevirtual #5                  // Method m2:()V</span><br><span class="line">        <span class="number">20</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">6</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">7</span>: <span class="number">10</span></span><br><span class="line">        line <span class="number">8</span>: <span class="number">20</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">21</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m1</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">4</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: ldc           #6                  // String 123</span><br><span class="line">         <span class="number">2</span>: astore_1</span><br><span class="line">         3: ldc           #7                  // String 456</span><br><span class="line">         <span class="number">5</span>: astore_2</span><br><span class="line">         6: new           #8                  // class java/lang/StringBuilder</span><br><span class="line">         <span class="number">9</span>: dup</span><br><span class="line">        10: invokespecial #9                  // Method java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">        <span class="number">13</span>: aload_1</span><br><span class="line">        14: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">        <span class="number">17</span>: aload_2</span><br><span class="line">        18: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">        21: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">        <span class="number">24</span>: astore_3</span><br><span class="line">        25: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">28</span>: aload_3</span><br><span class="line">        29: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">        <span class="number">32</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">11</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">3</span></span><br><span class="line">        line <span class="number">13</span>: <span class="number">6</span></span><br><span class="line">        line <span class="number">14</span>: <span class="number">25</span></span><br><span class="line">        line <span class="number">15</span>: <span class="number">32</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">33</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test3;</span><br><span class="line">            <span class="number">3</span>      <span class="number">30</span>     <span class="number">1</span>    s1   Ljava/lang/String;</span><br><span class="line">            <span class="number">6</span>      <span class="number">27</span>     <span class="number">2</span>    s2   Ljava/lang/String;</span><br><span class="line">           <span class="number">25</span>       <span class="number">8</span>     <span class="number">3</span>    s3   Ljava/lang/String;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m2</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">5</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: ldc           #6                  // String 123</span><br><span class="line">         <span class="number">2</span>: astore_1</span><br><span class="line">         3: ldc           #7                  // String 456</span><br><span class="line">         <span class="number">5</span>: astore_2</span><br><span class="line">         6: new           #8                  // class java/lang/StringBuilder</span><br><span class="line">         <span class="number">9</span>: dup</span><br><span class="line">        10: invokespecial #9                  // Method java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">        <span class="number">13</span>: astore_3</span><br><span class="line">        <span class="number">14</span>: aload_3</span><br><span class="line">        <span class="number">15</span>: aload_1</span><br><span class="line">        16: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">        <span class="number">19</span>: pop</span><br><span class="line">        <span class="number">20</span>: aload_3</span><br><span class="line">        <span class="number">21</span>: aload_2</span><br><span class="line">        22: invokevirtual #10                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">        <span class="number">25</span>: pop</span><br><span class="line">        <span class="number">26</span>: aload_3</span><br><span class="line">        27: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">        <span class="number">30</span>: astore        <span class="number">4</span></span><br><span class="line">        32: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">35</span>: aload         <span class="number">4</span></span><br><span class="line">        37: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">        <span class="number">40</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">18</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">19</span>: <span class="number">3</span></span><br><span class="line">        line <span class="number">20</span>: <span class="number">6</span></span><br><span class="line">        line <span class="number">21</span>: <span class="number">14</span></span><br><span class="line">        line <span class="number">22</span>: <span class="number">20</span></span><br><span class="line">        line <span class="number">23</span>: <span class="number">26</span></span><br><span class="line">        line <span class="number">24</span>: <span class="number">32</span></span><br><span class="line">        line <span class="number">25</span>: <span class="number">40</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">41</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test3;</span><br><span class="line">            <span class="number">3</span>      <span class="number">38</span>     <span class="number">1</span>    s1   Ljava/lang/String;</span><br><span class="line">            <span class="number">6</span>      <span class="number">35</span>     <span class="number">2</span>    s2   Ljava/lang/String;</span><br><span class="line">           <span class="number">14</span>      <span class="number">27</span>     <span class="number">3</span>    sb   Ljava/lang/StringBuilder;</span><br><span class="line">           <span class="number">32</span>       <span class="number">9</span>     <span class="number">4</span>    s3   Ljava/lang/String;</span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"Test3.java"</span></span><br></pre></td></tr></table></figure>
<p>从解字节码中可以看出，m1()方法源码中是使用+号拼接，但是在字节码中也被编译成了StringBuilder方式。</p>
<p>所以，可以得出结论，字符串拼接，+号和StringBuilder是相等的，效率一样。</p>
<p>接下来，我们再看一个案例：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.test.jvm;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Test4</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">new</span> Test4().m1();</span><br><span class="line">        <span class="keyword">new</span> Test4().m2();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m1</span><span class="params">()</span></span>&#123;</span><br><span class="line">        String str = <span class="string">""</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">            str = str + i;</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(str);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m2</span><span class="params">()</span></span>&#123;</span><br><span class="line">        StringBuilder sb = <span class="keyword">new</span> StringBuilder();</span><br><span class="line">        <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++) &#123;</span><br><span class="line">            sb.append(i);</span><br><span class="line">        &#125;</span><br><span class="line">        System.out.println(sb.toString());</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>m1() 与 m2() 哪个方法的效率高？</p>
<p>依然是通过字节码的方式进行探究。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br></pre></td><td class="code"><pre><span class="line">Classfile /F:/code/test-jvm/test-jvm-test/target/classes/cn/test/jvm/Test4.class</span><br><span class="line">  MD5 checksum f87a55446b8b6cd88b6e54bd5edcc9dc</span><br><span class="line">  Compiled from <span class="string">"Test4.java"</span></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">cn</span>.<span class="title">test</span>.<span class="title">jvm</span>.<span class="title">Test4</span></span></span><br><span class="line">  minor version: 0</span><br><span class="line">  major version: <span class="number">52</span></span><br><span class="line">  flags: ACC_PUBLIC, ACC_SUPER</span><br><span class="line">Constant pool:</span><br><span class="line">   #1 = Methodref          #14.#39        // java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">   #2 = Class              #40            // cn/test/jvm/Test4</span><br><span class="line">   #3 = Methodref          #2.#39         // cn/test/jvm/Test4."&lt;init&gt;":()V</span><br><span class="line">   #4 = Methodref          #2.#41         // cn/test/jvm/Test4.m1:()V</span><br><span class="line">   #5 = Methodref          #2.#42         // cn/test/jvm/Test4.m2:()V</span><br><span class="line">   #6 = String             #43            //</span><br><span class="line">   #7 = Class              #44            // java/lang/StringBuilder</span><br><span class="line">   #8 = Methodref          #7.#39         // java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">   #9 = Methodref          #7.#45         // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #10 = Methodref          #7.#46         // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">  #11 = Methodref          #7.#47         // java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">  #12 = Fieldref           #48.#49        // java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">  #13 = Methodref          #50.#51        // java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">  #14 = Class              #52            // java/lang/Object</span><br><span class="line">  #15 = Utf8               &lt;init&gt;</span><br><span class="line">  #16 = Utf8               ()V</span><br><span class="line">  #17 = Utf8               Code</span><br><span class="line">  #18 = Utf8               LineNumberTable</span><br><span class="line">  #19 = Utf8               LocalVariableTable</span><br><span class="line">  #20 = Utf8               this</span><br><span class="line">  #21 = Utf8               Lcn/test/jvm/Test4;</span><br><span class="line">  #22 = Utf8               main</span><br><span class="line">  #23 = Utf8               ([Ljava/lang/String;)V</span><br><span class="line">  #24 = Utf8               args</span><br><span class="line">  #25 = Utf8               [Ljava/lang/String;</span><br><span class="line">  #26 = Utf8               m1</span><br><span class="line">  #27 = Utf8               i</span><br><span class="line">  #28 = Utf8               I</span><br><span class="line">  #29 = Utf8               str</span><br><span class="line">  #30 = Utf8               Ljava/lang/String;</span><br><span class="line">  #31 = Utf8               StackMapTable</span><br><span class="line">  #32 = Class              #53            // java/lang/String</span><br><span class="line">  #33 = Utf8               m2</span><br><span class="line">  #34 = Utf8               sb</span><br><span class="line">  #35 = Utf8               Ljava/lang/StringBuilder;</span><br><span class="line">  #36 = Class              #44            // java/lang/StringBuilder</span><br><span class="line">  #37 = Utf8               SourceFile</span><br><span class="line">  #38 = Utf8               Test4.java</span><br><span class="line">  #39 = NameAndType        #15:#16        // "&lt;init&gt;":()V</span><br><span class="line">  #40 = Utf8               cn/test/jvm/Test4</span><br><span class="line">  #41 = NameAndType        #26:#16        // m1:()V</span><br><span class="line">  #42 = NameAndType        #33:#16        // m2:()V</span><br><span class="line">  #43 = Utf8</span><br><span class="line">  #44 = Utf8               java/lang/StringBuilder</span><br><span class="line">  #45 = NameAndType        #54:#55        // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #46 = NameAndType        #54:#56        // append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">  #47 = NameAndType        #57:#58        // toString:()Ljava/lang/String;</span><br><span class="line">  #48 = Class              #59            // java/lang/System</span><br><span class="line">  #49 = NameAndType        #60:#61        // out:Ljava/io/PrintStream;</span><br><span class="line">  #50 = Class              #62            // java/io/PrintStream</span><br><span class="line">  #51 = NameAndType        #63:#64        // println:(Ljava/lang/String;)V</span><br><span class="line">  #52 = Utf8               java/lang/Object</span><br><span class="line">  #53 = Utf8               java/lang/String</span><br><span class="line">  #54 = Utf8               append</span><br><span class="line">  #55 = Utf8               (Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">  #56 = Utf8               (I)Ljava/lang/StringBuilder;</span><br><span class="line">  #57 = Utf8               toString</span><br><span class="line">  #58 = Utf8               ()Ljava/lang/String;</span><br><span class="line">  #59 = Utf8               java/lang/System</span><br><span class="line">  #60 = Utf8               out</span><br><span class="line">  #61 = Utf8               Ljava/io/PrintStream;</span><br><span class="line">  #62 = Utf8               java/io/PrintStream</span><br><span class="line">  #63 = Utf8               println</span><br><span class="line">  #64 = Utf8               (Ljava/lang/String;)V</span><br><span class="line">&#123;</span><br><span class="line">  <span class="keyword">public</span> cn.test.jvm.Test4();</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">1</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         <span class="number">0</span>: aload_0</span><br><span class="line">         1: invokespecial #1                  // Method java/lang/Object."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">4</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">3</span>: <span class="number">0</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>       <span class="number">5</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test4;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(java.lang.String[])</span></span>;</span><br><span class="line">    descriptor: ([Ljava/lang/String;)V</span><br><span class="line">    flags: ACC_PUBLIC, ACC_STATIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">1</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: new           #2                  // class cn/test/jvm/Test4</span><br><span class="line">         <span class="number">3</span>: dup</span><br><span class="line">         4: invokespecial #3                  // Method "&lt;init&gt;":()V</span><br><span class="line">         7: invokevirtual #4                  // Method m1:()V</span><br><span class="line">        10: new           #2                  // class cn/test/jvm/Test4</span><br><span class="line">        <span class="number">13</span>: dup</span><br><span class="line">        14: invokespecial #3                  // Method "&lt;init&gt;":()V</span><br><span class="line">        17: invokevirtual #5                  // Method m2:()V</span><br><span class="line">        <span class="number">20</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">6</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">7</span>: <span class="number">10</span></span><br><span class="line">        line <span class="number">8</span>: <span class="number">20</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">0</span>      <span class="number">21</span>     <span class="number">0</span>  args   [Ljava/lang/String;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m1</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">3</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: ldc           #6                  // String</span><br><span class="line">         <span class="number">2</span>: astore_1  <span class="comment">// 将空字符串压入到本地变量表中的下标为1的位置</span></span><br><span class="line">         <span class="number">3</span>: iconst_0  <span class="comment">// 将数字0压入操作栈顶</span></span><br><span class="line">         <span class="number">4</span>: istore_2  <span class="comment">// 将栈顶数字0压入到本地变量表中的下标为2的位置</span></span><br><span class="line">         <span class="number">5</span>: iload_2  <span class="comment">// 将本地变量中下标为2的数字0压入操作栈顶</span></span><br><span class="line">         <span class="number">6</span>: iconst_5 <span class="comment">// 将数字5压入操作栈顶</span></span><br><span class="line">         <span class="number">7</span>: if_icmpge     <span class="number">35</span>  <span class="comment">//比较栈顶两int型数值大小，当结果大于等于0时跳转到35</span></span><br><span class="line">        10: new           #7                  // class java/lang/StringBuilder</span><br><span class="line">        <span class="number">13</span>: dup  <span class="comment">//复制栈顶数值并将复制值压入栈顶(数字5)</span></span><br><span class="line">        14: invokespecial #8                  // Method java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">        <span class="number">17</span>: aload_1</span><br><span class="line">        18: invokevirtual #9                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;</span><br><span class="line">        <span class="number">21</span>: iload_2 <span class="comment">//将本地变量中下标为2的数字0压入操作栈顶</span></span><br><span class="line">        22: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">        25: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">        <span class="number">28</span>: astore_1</span><br><span class="line">        <span class="number">29</span>: iinc          <span class="number">2</span>, <span class="number">1</span></span><br><span class="line">        <span class="number">32</span>: goto          <span class="number">5</span></span><br><span class="line">        35: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">38</span>: aload_1</span><br><span class="line">        39: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">        <span class="number">42</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">11</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">3</span></span><br><span class="line">        line <span class="number">13</span>: <span class="number">10</span></span><br><span class="line">        line <span class="number">12</span>: <span class="number">29</span></span><br><span class="line">        line <span class="number">15</span>: <span class="number">35</span></span><br><span class="line">        line <span class="number">16</span>: <span class="number">42</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">            <span class="number">5</span>      <span class="number">30</span>     <span class="number">2</span>     i   I</span><br><span class="line">            <span class="number">0</span>      <span class="number">43</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test4;</span><br><span class="line">            <span class="number">3</span>      <span class="number">40</span>     <span class="number">1</span>   str   Ljava/lang/String;</span><br><span class="line">      StackMapTable: number_of_entries = <span class="number">2</span></span><br><span class="line">        frame_type = <span class="number">253</span> <span class="comment">/* append */</span></span><br><span class="line">          offset_delta = <span class="number">5</span></span><br><span class="line">          locals = [ class java/lang/String, int ]</span><br><span class="line">        frame_type = <span class="number">250</span> <span class="comment">/* chop */</span></span><br><span class="line">          offset_delta = <span class="number">29</span></span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">m2</span><span class="params">()</span></span>;</span><br><span class="line">    descriptor: ()V</span><br><span class="line">    flags: ACC_PUBLIC</span><br><span class="line">    Code:</span><br><span class="line">      stack=<span class="number">2</span>, locals=<span class="number">3</span>, args_size=<span class="number">1</span></span><br><span class="line">         0: new           #7                  // class java/lang/StringBuilder</span><br><span class="line">         <span class="number">3</span>: dup</span><br><span class="line">         4: invokespecial #8                  // Method java/lang/StringBuilder."&lt;init&gt;":()V</span><br><span class="line">         <span class="number">7</span>: astore_1</span><br><span class="line">         <span class="number">8</span>: iconst_0</span><br><span class="line">         <span class="number">9</span>: istore_2</span><br><span class="line">        <span class="number">10</span>: iload_2</span><br><span class="line">        <span class="number">11</span>: iconst_5</span><br><span class="line">        <span class="number">12</span>: if_icmpge     <span class="number">27</span></span><br><span class="line">        <span class="number">15</span>: aload_1</span><br><span class="line">        <span class="number">16</span>: iload_2</span><br><span class="line">        17: invokevirtual #10                 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;</span><br><span class="line">        <span class="number">20</span>: pop</span><br><span class="line">        <span class="number">21</span>: iinc          <span class="number">2</span>, <span class="number">1</span></span><br><span class="line">        <span class="number">24</span>: goto          <span class="number">10</span></span><br><span class="line">        27: getstatic     #12                 // Field java/lang/System.out:Ljava/io/PrintStream;</span><br><span class="line">        <span class="number">30</span>: aload_1</span><br><span class="line">        31: invokevirtual #11                 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;</span><br><span class="line">        34: invokevirtual #13                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V</span><br><span class="line">        <span class="number">37</span>: <span class="keyword">return</span></span><br><span class="line">      LineNumberTable:</span><br><span class="line">        line <span class="number">19</span>: <span class="number">0</span></span><br><span class="line">        line <span class="number">20</span>: <span class="number">8</span></span><br><span class="line">        line <span class="number">21</span>: <span class="number">15</span></span><br><span class="line">        line <span class="number">20</span>: <span class="number">21</span></span><br><span class="line">        line <span class="number">23</span>: <span class="number">27</span></span><br><span class="line">        line <span class="number">24</span>: <span class="number">37</span></span><br><span class="line">      LocalVariableTable:</span><br><span class="line">        Start  Length  Slot  Name   Signature</span><br><span class="line">           <span class="number">10</span>      <span class="number">17</span>     <span class="number">2</span>     i   I</span><br><span class="line">            <span class="number">0</span>      <span class="number">38</span>     <span class="number">0</span>  <span class="keyword">this</span>   Lcn/test/jvm/Test4;</span><br><span class="line">            <span class="number">8</span>      <span class="number">30</span>     <span class="number">1</span>    sb   Ljava/lang/StringBuilder;</span><br><span class="line">      StackMapTable: number_of_entries = <span class="number">2</span></span><br><span class="line">        frame_type = <span class="number">253</span> <span class="comment">/* append */</span></span><br><span class="line">          offset_delta = <span class="number">10</span></span><br><span class="line">          locals = [ class java/lang/StringBuilder, int ]</span><br><span class="line">        frame_type = <span class="number">250</span> <span class="comment">/* chop */</span></span><br><span class="line">          offset_delta = <span class="number">16</span></span><br><span class="line">&#125;</span><br><span class="line">SourceFile: <span class="string">"Test4.java"</span></span><br></pre></td></tr></table></figure>
<p>可以看到，m1()方法中的循环体内，每一次循环都会创建StringBuilder对象，效率低于m2()方法。</p>
<h3 id="2-7、小结"><a href="#2-7、小结" class="headerlink" title="2.7、小结"></a>2.7、小结</h3><p>使用字节码的方式可以很好查看代码底层的执行，从而可以看出哪些实现效率高，哪些实现效率低。可以更好的对我们的代码做优化。让程序执行效率更高。</p>
<h2 id="3、代码优化"><a href="#3、代码优化" class="headerlink" title="3、代码优化"></a>3、代码优化</h2><p>优化，不仅仅是在运行环境进行优化，还需要在代码本身做优化，如果代码本身存在性能问题，那么在其他方面再怎么优化也不可能达到效果最优的。</p>
<h3 id="3-1、尽可能使用局部变量"><a href="#3-1、尽可能使用局部变量" class="headerlink" title="3.1、尽可能使用局部变量"></a>3.1、尽可能使用局部变量</h3><p>调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中速度较快，其他变量，如静态变量、实例变量等，都在堆中创建，速度较慢。另外，栈中创建的变量，随着方法的运行结束，这些内容就没了，不需要额外的垃圾回收。</p>
<h3 id="3-2、尽量减少对变量的重复计算"><a href="#3-2、尽量减少对变量的重复计算" class="headerlink" title="3.2、尽量减少对变量的重复计算"></a>3.2、尽量减少对变量的重复计算</h3><p>明确一个概念，对方法的调用，即使方法中只有一句语句，也是有消耗的。所以例如下面的操作：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; list.size(); i++)</span><br><span class="line">&#123;...&#125;</span><br></pre></td></tr></table></figure>
<p>建议替换为：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">int</span> length = list.size();</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>,  i &lt; length; i++)</span><br><span class="line"></span><br><span class="line">&#123;...&#125;</span><br></pre></td></tr></table></figure>
<p>这样，在list.size()很大的时候，就减少了很多的消耗。</p>
<h3 id="3-3、尽量采用懒加载的策略，即在需要的时候才创建"><a href="#3-3、尽量采用懒加载的策略，即在需要的时候才创建" class="headerlink" title="3.3、尽量采用懒加载的策略，即在需要的时候才创建"></a>3.3、尽量采用懒加载的策略，即在需要的时候才创建</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">String str = <span class="string">"aaa"</span>;</span><br><span class="line"><span class="keyword">if</span> (i == <span class="number">1</span>)&#123;</span><br><span class="line">　　list.add(str);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">//建议替换成</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> (i == <span class="number">1</span>)&#123;</span><br><span class="line">　　String str = <span class="string">"aaa"</span>;</span><br><span class="line">　　list.add(str);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="3-4、异常不应该用来控制程序流程"><a href="#3-4、异常不应该用来控制程序流程" class="headerlink" title="3.4、异常不应该用来控制程序流程"></a>3.4、异常不应该用来控制程序流程</h3><p>异常对性能不利。抛出异常首先要创建一个新的对象，Throwable接口的构造函数调用名为fillInStackTrace()的本地同步方 法，fillInStackTrace()方法检查堆栈，收集调用跟踪信息。只要有异常被抛出，Java虚拟机就必须调整调用堆栈，因为在处理过程中创建 了一个新的对象。异常只能用于错误处理，不应该用来控制程序流程。</p>
<h3 id="3-5、不要将数组声明为public-static-final"><a href="#3-5、不要将数组声明为public-static-final" class="headerlink" title="3.5、不要将数组声明为public static final"></a>3.5、不要将数组声明为public static final</h3><p>因为这毫无意义，这样只是定义了引用为static final，数组的内容还是可以随意改变的，将数组声明为public更是一个安全漏洞，这意味着这个数组可以被外部类所改变。</p>
<h3 id="3-6、不要创建一些不使用的对象，不要导入一些不使用的类"><a href="#3-6、不要创建一些不使用的对象，不要导入一些不使用的类" class="headerlink" title="3.6、不要创建一些不使用的对象，不要导入一些不使用的类"></a>3.6、不要创建一些不使用的对象，不要导入一些不使用的类</h3><p>这毫无意义，如果代码中出现”The value of the local variable i is not used”、”The import java.util is never used”，那么请删除这些无用的内容</p>
<h3 id="3-7、程序运行过程中避免使用反射"><a href="#3-7、程序运行过程中避免使用反射" class="headerlink" title="3.7、程序运行过程中避免使用反射"></a>3.7、程序运行过程中避免使用反射</h3><p>反射是Java提供给用户一个很强大的功能，功能强大往往意味着效率不高。不建议在程序运行过程中使用尤其是频繁使用反射机制，特别是 Method的invoke方法。</p>
<p>如果确实有必要，一种建议性的做法是将那些需要通过反射加载的类在项目启动的时候通过反射实例化出一个对象并放入内存。</p>
<h3 id="3-8、使用数据库连接池和线程池"><a href="#3-8、使用数据库连接池和线程池" class="headerlink" title="3.8、使用数据库连接池和线程池"></a>3.8、使用数据库连接池和线程池</h3><p>这两个池都是用于重用对象的，前者可以避免频繁地打开和关闭连接，后者可以避免频繁地创建和销毁线程。</p>
<h3 id="3-9、容器初始化时尽可能指定长度"><a href="#3-9、容器初始化时尽可能指定长度" class="headerlink" title="3.9、容器初始化时尽可能指定长度"></a>3.9、容器初始化时尽可能指定长度</h3><p>容器初始化时尽可能指定长度，如：new ArrayList&lt;&gt;(10); new HashMap&lt;&gt;(32); 避免容器长度不足时，扩容带来的性能损耗。</p>
<h3 id="3-10、ArrayList随机遍历快，LinkedList添加删除快"><a href="#3-10、ArrayList随机遍历快，LinkedList添加删除快" class="headerlink" title="3.10、ArrayList随机遍历快，LinkedList添加删除快"></a>3.10、ArrayList随机遍历快，LinkedList添加删除快</h3><h3 id="3-11、使用Entry遍历Map"><a href="#3-11、使用Entry遍历Map" class="headerlink" title="3.11、使用Entry遍历Map"></a>3.11、使用Entry遍历Map</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Map&lt;String,String&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line"><span class="keyword">for</span> (Map.Entry&lt;String,String&gt; entry : map.entrySet()) &#123;</span><br><span class="line">    String key = entry.getKey();</span><br><span class="line">    String value = entry.getValue();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>避免使用这种方式：</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Map&lt;String,String&gt; map = <span class="keyword">new</span> HashMap&lt;&gt;();</span><br><span class="line"><span class="keyword">for</span> (String key : map.keySet()) &#123;</span><br><span class="line">    String value = map.get(key);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h3 id="3-12、不要手动调用System-gc"><a href="#3-12、不要手动调用System-gc" class="headerlink" title="3.12、不要手动调用System.gc();"></a>3.12、不要手动调用System.gc();</h3><h3 id="3-13、String尽量少用正则表达式"><a href="#3-13、String尽量少用正则表达式" class="headerlink" title="3.13、String尽量少用正则表达式"></a>3.13、String尽量少用正则表达式</h3><p>正则表达式虽然功能强大，但是其效率较低，除非是有需要，否则尽可能少用。</p>
<p>replace()  不支持正则<br>replaceAll() 支持正则</p>
<p>如果仅仅是字符的替换建议使用replace()。</p>
<h3 id="3-14、日志的输出要注意级别"><a href="#3-14、日志的输出要注意级别" class="headerlink" title="3.14、日志的输出要注意级别"></a>3.14、日志的输出要注意级别</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 当前的日志级别是error</span></span><br><span class="line">LOGGER.info(<span class="string">"保存出错！"</span> + user);</span><br></pre></td></tr></table></figure>
<h3 id="3-15、对资源的close-建议分开操作"><a href="#3-15、对资源的close-建议分开操作" class="headerlink" title="3.15、对资源的close()建议分开操作"></a>3.15、对资源的close()建议分开操作</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">try</span>&#123;</span><br><span class="line">    XXX.close();</span><br><span class="line">    YYY.close();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">catch</span> (Exception e)&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 建议改为</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">try</span>&#123;</span><br><span class="line">    XXX.close();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">catch</span> (Exception e)&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">try</span>&#123;</span><br><span class="line"></span><br><span class="line">    YYY.close();</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">catch</span> (Exception e)&#123;</span><br><span class="line">    ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/28/JVM-优化/" data-id="ckcc5iwij0009q4uwezohgeso" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/jvm/">jvm</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-Jvm-GC" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/28/Jvm-GC/" class="article-date">
  <time datetime="2018-12-28T02:49:26.000Z" itemprop="datePublished">2018-12-28</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/28/Jvm-GC/">JVM-GC</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="JVM-GC"><a href="#JVM-GC" class="headerlink" title="JVM - GC"></a>JVM - GC</h2><h2 id="1、垃圾回收"><a href="#1、垃圾回收" class="headerlink" title="1、垃圾回收"></a>1、垃圾回收</h2><p>程序的运行必然需要申请内存资源，无效的对象资源如果不及时处理就会一直占有内存资源，最终将导致内存溢出，所以对内存资源的管理是非常重要了。</p>
<h3 id="1-1、C-C-语言的垃圾回收"><a href="#1-1、C-C-语言的垃圾回收" class="headerlink" title="1.1、C/C++语言的垃圾回收"></a>1.1、C/C++语言的垃圾回收</h3><p>在C/C++语言中，没有自动垃圾回收机制，是通过new关键字申请内存资源，通过delete关键字释放内存资源。</p>
<p>如果，程序员在某些位置没有写delete进行释放，那么申请的对象将一直占用内存资源，最终可能会导致内存溢出。</p>
<h3 id="1-2、Java语言的垃圾回收"><a href="#1-2、Java语言的垃圾回收" class="headerlink" title="1.2、Java语言的垃圾回收"></a>1.2、Java语言的垃圾回收</h3><p>为了让程序员更专注于代码的实现，而不用过多的考虑内存释放的问题，所以，在Java语言中，有了自动的垃圾回收机制，也就是我们熟悉的GC。</p>
<p>有了垃圾回收机制后，程序员只需要关心内存的申请即可，内存的释放由系统自动识别完成。</p>
<p>换句话说，自动的垃圾回收的算法就会变得非常重要了，如果因为算法的不合理，导致内存资源一直没有释放，同样也可能会导致内存溢出的。</p>
<p>当然，除了Java语言，C#、Python等语言也都有自动的垃圾回收机制。</p>
<h2 id="2、垃圾回收的常见算法"><a href="#2、垃圾回收的常见算法" class="headerlink" title="2、垃圾回收的常见算法"></a>2、垃圾回收的常见算法</h2><p>自动化的管理内存资源，垃圾回收机制必须要有一套算法来进行计算，哪些是有效的对象，哪些是无效的对象，对于无效的对象就要进行回收处理。</p>
<p>常见的垃圾回收算法有：引用计数法、标记清除法、标记压缩法、复制算法、分代算法等。</p>
<h3 id="2-1、引用计数法"><a href="#2-1、引用计数法" class="headerlink" title="2.1、引用计数法"></a>2.1、引用计数法</h3><p>引用计数是历史最悠久的一种算法，最早George E. Collins在1960的时候首次提出，50年后的今天，该算法依然被很多编程语言使用。</p>
<h4 id="2-1-1、原理"><a href="#2-1-1、原理" class="headerlink" title="2.1.1、原理"></a>2.1.1、原理</h4><p>假设有一个对象A，任何一个对象对A的引用，那么对象A的引用计数器+1，当引用失败时，对象A的引用计数器就-1，如果对象A的计数器的值为0，就说明对象A没有引用了，可以被回收。</p>
<h4 id="2-1-2、优缺点"><a href="#2-1-2、优缺点" class="headerlink" title="2.1.2、优缺点"></a>2.1.2、优缺点</h4><p>优点：</p>
<ul>
<li>实时性较高，无需等到内存不够的时候，才开始回收，运行时根据对象的计数器是否为0，就可以直接回收。</li>
<li>在垃圾回收过程中，应用无需挂起。如果申请内存时，内存不足，则立刻报outofmember 错误。</li>
<li>区域性，更新对象的计数器时，只是影响到该对象，不会扫描全部对象。</li>
</ul>
<p>缺点：</p>
<ul>
<li>每次对象被引用时，都需要去更新计数器，有一点时间开销。</li>
<li>浪费CPU资源，即使内存够用，仍然在运行时进行计数器的统计。</li>
<li>无法解决循环引用问题。（最大的缺点）</li>
</ul>
<p>什么是循环引用？</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestA</span></span>&#123;</span><br><span class="line">  <span class="keyword">public</span> TestB b;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">TestB</span></span>&#123;</span><br><span class="line">  <span class="keyword">public</span> TestA a;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">Main</span></span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span></span>&#123;</span><br><span class="line">        A a = <span class="keyword">new</span> A();</span><br><span class="line">        B b = <span class="keyword">new</span> B();</span><br><span class="line">        a.b=b;</span><br><span class="line">        b.a=a;</span><br><span class="line">        a = <span class="keyword">null</span>;</span><br><span class="line">        b = <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>虽然a和b都为null，但是由于a和b存在循环引用，这样a和b永远都不会被回收。</p>
<h3 id="2-2、标记清除法"><a href="#2-2、标记清除法" class="headerlink" title="2.2、标记清除法"></a>2.2、标记清除法</h3><p>标记清除算法，是将垃圾回收分为2个阶段，分别是标记和清除。</p>
<ul>
<li>标记：从根节点开始标记引用的对象。</li>
<li>清除：未被标记引用的对象就是垃圾对象，可以被清理。</li>
</ul>
<h4 id="2-2-1、原理"><a href="#2-2-1、原理" class="headerlink" title="2.2.1、原理"></a>2.2.1、原理</h4><p> <img src="https://threadv.github.io/assets2/19222114-6435e25e050f4a2ea3230879392bdfb3.jpg" alt="19222114-6435e25e050f4a2ea3230879392bdfb3"></p>
<p>这张图代表的是程序运行期间所有对象的状态，它们的标志位全部是0（也就是未标记，以下默认0就是未标记，1为已标记），假设这会儿有效内存空间耗尽了，JVM将会停止应用程序的运行并开启GC线程，然后开始进行标记工作，按照根搜索算法，标记完以后，对象的状态如下图。</p>
<p> <img src="https://threadv.github.io/assets2/19222543-1da7fb7bc5d24fd18872a267b65e939e.jpg" alt="img"></p>
<p>可以看到，按照根搜索算法，所有从root对象可达的对象就被标记为了存活的对象，此时已经完成了第一阶段标记。接下来，就要执行第二阶段清除了，那么清除完以后，剩下的对象以及对象的状态如下图所示。</p>
<p> <img src="https://threadv.github.io/assets2/19222820-8eca1c1518754d8fac6da532b13f746b.jpg" alt="img"></p>
<p>可以看到，没有被标记的对象将会回收清除掉，而被标记的对象将会留下，并且会将标记位重新归0。接下来就不用说了，唤醒停止的程序线程，让程序继续运行即可。</p>
<h4 id="2-2-2、优缺点"><a href="#2-2-2、优缺点" class="headerlink" title="2.2.2、优缺点"></a>2.2.2、优缺点</h4><p>可以看到，标记清除算法解决了引用计数算法中的循环引用的问题，没有从root节点引用的对象都会被回收。</p>
<p>同样，标记清除算法也是有缺点的：</p>
<ul>
<li>效率较低，标记和清除两个动作都需要遍历所有的对象，并且在GC时，需要停止应用程序，对于交互性要求比较高的应用而言这个体验是非常差的。</li>
<li>通过标记清除算法清理出来的内存，碎片化较为严重，因为被回收的对象可能存在于内存的各个角落，所以清理出来的内存是不连贯的。</li>
</ul>
<h3 id="2-3、标记压缩算法"><a href="#2-3、标记压缩算法" class="headerlink" title="2.3、标记压缩算法"></a>2.3、标记压缩算法</h3><p>标记压缩算法是在标记清除算法的基础之上，做了优化改进的算法。和标记清除算法一样，也是从根节点开始，对对象的引用进行标记，在清理阶段，并不是简单的清理未标记的对象，而是将存活的对象压缩到内存的一端，然后清理边界以外的垃圾，从而解决了碎片化的问题。</p>
<h4 id="2-3-1、原理"><a href="#2-3-1、原理" class="headerlink" title="2.3.1、原理"></a>2.3.1、原理</h4><p> <img src="https://threadv.github.io/assets2/5b82c8100001b6ec07200388.jpg" alt="img"></p>
<h4 id="2-3-2、优缺点"><a href="#2-3-2、优缺点" class="headerlink" title="2.3.2、优缺点"></a>2.3.2、优缺点</h4><p>优缺点同标记清除算法，解决了标记清除算法的碎片化的问题，同时，标记压缩算法多了一步，对象移动内存位置的步骤，其效率也有有一定的影响。</p>
<h3 id="2-4、复制算法"><a href="#2-4、复制算法" class="headerlink" title="2.4、复制算法"></a>2.4、复制算法</h3><p>复制算法的核心就是，将原有的内存空间一分为二，每次只用其中的一块，在垃圾回收时，将正在使用的对象复制到另一个内存空间中，然后将该内存空间清空，交换两个内存的角色，完成垃圾的回收。</p>
<p>如果内存中的垃圾对象较多，需要复制的对象就较少，这种情况下适合使用该方式并且效率比较高，反之，则不适合。 </p>
<p> <img src="https://threadv.github.io/assets2/5b82c80f000133c207200396.jpg" alt="img"></p>
<h4 id="2-4-1、JVM中年轻代内存空间"><a href="#2-4-1、JVM中年轻代内存空间" class="headerlink" title="2.4.1、JVM中年轻代内存空间"></a>2.4.1、JVM中年轻代内存空间</h4><p><img src="https://threadv.github.io/assets2/young_gc.png" alt="young_gc"></p>
<ol>
<li>在GC开始的时候，对象只会存在于Eden区和名为“From”的Survivor区，Survivor区“To”是空的。</li>
<li>紧接着进行GC，Eden区中所有存活的对象都会被复制到“To”，而在“From”区中，仍存活的对象会根据他们的年龄值来决定去向。年龄达到一定值(年龄阈值，可以通过-XX:MaxTenuringThreshold来设置)的对象会被移动到年老代中，没有达到阈值的对象会被复制到“To”区域。</li>
<li>经过这次GC后，Eden区和From区已经被清空。这个时候，“From”和“To”会交换他们的角色，也就是新的“To”就是上次GC前的“From”，新的“From”就是上次GC前的“To”。不管怎样，都会保证名为To的Survivor区域是空的。</li>
<li>GC会一直重复这样的过程，直到“To”区被填满，“To”区被填满之后，会将所有对象移动到年老代中。</li>
</ol>
<h4 id="2-4-2、优缺点"><a href="#2-4-2、优缺点" class="headerlink" title="2.4.2、优缺点"></a>2.4.2、优缺点</h4><p>优点：</p>
<ul>
<li>在垃圾对象多的情况下，效率较高</li>
<li>清理后，内存无碎片</li>
</ul>
<p>缺点：</p>
<ul>
<li>在垃圾对象少的情况下，不适用，如：老年代内存</li>
<li>分配的2块内存空间，在同一个时刻，只能使用一半，内存使用率较低</li>
</ul>
<h3 id="2-5、分代算法"><a href="#2-5、分代算法" class="headerlink" title="2.5、分代算法"></a>2.5、分代算法</h3><p>前面介绍了多种回收算法，每一种算法都有自己的优点也有缺点，谁都不能替代谁，所以根据垃圾回收对象的特点进行选择，才是明智的选择。</p>
<p>分代算法其实就是这样的，根据回收对象的特点进行选择，在jvm中，年轻代适合使用复制算法，老年代适合使用标记清除或标记压缩算法。</p>
<h2 id="3、垃圾收集器以及内存分配"><a href="#3、垃圾收集器以及内存分配" class="headerlink" title="3、垃圾收集器以及内存分配"></a>3、垃圾收集器以及内存分配</h2><p>前面我们讲了垃圾回收的算法，还需要有具体的实现，在jvm中，实现了多种垃圾收集器，包括：串行垃圾收集器、并行垃圾收集器、CMS（并发）垃圾收集器、G1垃圾收集器，接下来，我们一个个的了解学习。</p>
<h3 id="3-1、串行垃圾收集器"><a href="#3-1、串行垃圾收集器" class="headerlink" title="3.1、串行垃圾收集器"></a>3.1、串行垃圾收集器</h3><p>串行垃圾收集器，是指使用单线程进行垃圾回收，垃圾回收时，只有一个线程在工作，并且java应用中的所有线程都要暂停，等待垃圾回收的完成。这种现象称之为STW（Stop-The-World）。</p>
<p>对于交互性较强的应用而言，这种垃圾收集器是不能够接受的。</p>
<p>一般在Javaweb应用中是不会采用该收集器的。</p>
<h4 id="3-1-1、编写测试代码"><a href="#3-1-1、编写测试代码" class="headerlink" title="3.1.1、编写测试代码"></a>3.1.1、编写测试代码</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> cn.test.jvm;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Properties;</span><br><span class="line"><span class="keyword">import</span> java.util.Random;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">TestGC</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        List&lt;Object&gt; list = <span class="keyword">new</span> ArrayList&lt;Object&gt;();</span><br><span class="line">        <span class="keyword">while</span> (<span class="keyword">true</span>)&#123;</span><br><span class="line">            <span class="keyword">int</span> sleep = <span class="keyword">new</span> Random().nextInt(<span class="number">100</span>);</span><br><span class="line">            <span class="keyword">if</span>(System.currentTimeMillis() % <span class="number">2</span> ==<span class="number">0</span>)&#123;</span><br><span class="line">                list.clear();</span><br><span class="line">            &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">10000</span>; i++) &#123;</span><br><span class="line">                    Properties properties = <span class="keyword">new</span> Properties();</span><br><span class="line">                    properties.put(<span class="string">"key_"</span>+i, <span class="string">"value_"</span> + System.currentTimeMillis() + i);</span><br><span class="line">                    list.add(properties);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">           <span class="comment">// System.out.println("list大小为：" + list.size());</span></span><br><span class="line"></span><br><span class="line">            Thread.sleep(sleep);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h4 id="3-1-2、设置垃圾回收为串行收集器"><a href="#3-1-2、设置垃圾回收为串行收集器" class="headerlink" title="3.1.2、设置垃圾回收为串行收集器"></a>3.1.2、设置垃圾回收为串行收集器</h4><p>在程序运行参数中添加2个参数，如下：</p>
<ul>
<li><p>-XX:+UseSerialGC</p>
<ul>
<li>指定年轻代和老年代都使用串行垃圾收集器</li>
</ul>
</li>
<li><p>-XX:+PrintGCDetails</p>
<ul>
<li>打印垃圾回收的详细信息</li>
</ul>
</li>
</ul>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span> 为了测试GC，将堆的初始和最大内存都设置为16M</span><br><span class="line">-XX:+UseSerialGC -XX:+PrintGCDetails -Xms16m -Xmx16m</span><br></pre></td></tr></table></figure>
<p> <img src="https://threadv.github.io/assets2/1537636794330.png" alt="1537636794330"></p>
<p>启动程序，可以看到下面信息：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[GC (Allocation Failure) [DefNew: 4416K-&gt;512K(4928K), 0.0046102 secs] 4416K-&gt;1973K(15872K), 0.0046533 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"></span><br><span class="line">[Full GC (Allocation Failure) [Tenured: 10944K-&gt;3107K(10944K), 0.0085637 secs] 15871K-&gt;3107K(15872K), [Metaspace: 3496K-&gt;3496K(1056768K)], 0.0085974 secs] [Times: user=0.02 sys=0.00, real=0.01 secs]</span><br></pre></td></tr></table></figure>
<p>GC日志信息解读：</p>
<p>年轻代的内存GC前后的大小：</p>
<ul>
<li>DefNew<ul>
<li>表示使用的是串行垃圾收集器。</li>
</ul>
</li>
<li>4416K-&gt;512K(4928K)<ul>
<li>表示，年轻代GC前，占有4416K内存，GC后，占有512K内存，总大小4928K</li>
</ul>
</li>
<li>0.0046102 secs<ul>
<li>表示，GC所用的时间，单位为毫秒。</li>
</ul>
</li>
<li>4416K-&gt;1973K(15872K)<ul>
<li>表示，GC前，堆内存占有4416K，GC后，占有1973K，总大小为15872K</li>
</ul>
</li>
<li>Full GC<ul>
<li>表示，内存空间全部进行GC</li>
</ul>
</li>
</ul>
<h3 id="3-2、并行垃圾收集器"><a href="#3-2、并行垃圾收集器" class="headerlink" title="3.2、并行垃圾收集器"></a>3.2、并行垃圾收集器</h3><p>并行垃圾收集器在串行垃圾收集器的基础之上做了改进，将单线程改为了多线程进行垃圾回收，这样可以缩短垃圾回收的时间。（这里是指，并行能力较强的机器）</p>
<p>当然了，并行垃圾收集器在收集的过程中也会暂停应用程序，这个和串行垃圾回收器是一样的，只是并行执行，速度更快些，暂停的时间更短一些。</p>
<h4 id="3-2-1、ParNew垃圾收集器"><a href="#3-2-1、ParNew垃圾收集器" class="headerlink" title="3.2.1、ParNew垃圾收集器"></a>3.2.1、ParNew垃圾收集器</h4><p>ParNew垃圾收集器是工作在年轻代上的，只是将串行的垃圾收集器改为了并行。</p>
<p>通过-XX:+UseParNewGC参数设置年轻代使用ParNew回收器，老年代使用的依然是串行收集器。</p>
<p>测试：</p>
<p> <img src="https://threadv.github.io/assets2/1537636907367.png" alt="1537636907367"></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>参数</span><br><span class="line">-XX:+UseParNewGC -XX:+PrintGCDetails -Xms16m -Xmx16m</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>打印出的信息</span><br><span class="line">[GC (Allocation Failure) [ParNew: 4416K-&gt;512K(4928K), 0.0032106 secs] 4416K-&gt;1988K(15872K), 0.0032697 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]</span><br></pre></td></tr></table></figure>
<p>由以上信息可以看出，<code>ParNew:</code> 使用的是ParNew收集器。其他信息和串行收集器一致。</p>
<h4 id="3-2-2、ParallelGC垃圾收集器"><a href="#3-2-2、ParallelGC垃圾收集器" class="headerlink" title="3.2.2、ParallelGC垃圾收集器"></a>3.2.2、ParallelGC垃圾收集器</h4><p>ParallelGC收集器工作机制和ParNewGC收集器一样，只是在此基础之上，新增了两个和系统吞吐量相关的参数，使得其使用起来更加的灵活和高效。</p>
<p>相关参数如下：</p>
<ul>
<li>-XX:+UseParallelGC<ul>
<li>年轻代使用ParallelGC垃圾回收器，老年代使用串行回收器。</li>
</ul>
</li>
<li>-XX:+UseParallelOldGC<ul>
<li>年轻代使用ParallelGC垃圾回收器，老年代使用ParallelOldGC垃圾回收器。</li>
</ul>
</li>
<li>-XX:MaxGCPauseMillis<ul>
<li>设置最大的垃圾收集时的停顿时间，单位为毫秒</li>
<li>需要注意的时，ParallelGC为了达到设置的停顿时间，可能会调整堆大小或其他的参数，如果堆的大小设置的较小，就会导致GC工作变得很频繁，反而可能会影响到性能。</li>
<li>该参数使用需谨慎。</li>
</ul>
</li>
<li>-XX:GCTimeRatio<ul>
<li>设置垃圾回收时间占程序运行时间的百分比，公式为1/(1+n)。</li>
<li>它的值为0~100之间的数字，默认值为99，也就是垃圾回收时间不能超过1%</li>
</ul>
</li>
<li>-XX:UseAdaptiveSizePolicy<ul>
<li>自适应GC模式，垃圾回收器将自动调整年轻代、老年代等参数，达到吞吐量、堆大小、停顿时间之间的平衡。</li>
<li>一般用于，手动调整参数比较困难的场景，让收集器自动进行调整。</li>
</ul>
</li>
</ul>
<p>测试： <img src="https://threadv.github.io/assets2/1537637452047.png" alt="1537637452047"></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>参数</span><br><span class="line">-XX:+UseParallelGC -XX:+UseParallelOldGC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xms16m -Xmx16m</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>打印的信息</span><br><span class="line">[GC (Allocation Failure) [PSYoungGen: 4096K-&gt;480K(4608K)] 4096K-&gt;1840K(15872K), 0.0034307 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"></span><br><span class="line">[Full GC (Ergonomics) [PSYoungGen: 505K-&gt;0K(4608K)] [ParOldGen: 10332K-&gt;10751K(11264K)] 10837K-&gt;10751K(15872K), [Metaspace: 3491K-&gt;3491K(1056768K)], 0.0793622 secs] [Times: user=0.13 sys=0.00, real=0.08 secs]</span><br></pre></td></tr></table></figure>
<p>有以上信息可以看出，年轻代和老年代都使用了ParallelGC垃圾回收器。</p>
<h3 id="3-3、CMS垃圾收集器"><a href="#3-3、CMS垃圾收集器" class="headerlink" title="3.3、CMS垃圾收集器"></a>3.3、CMS垃圾收集器</h3><p>CMS全称 Concurrent Mark Sweep，是一款并发的、使用标记-清除算法的垃圾回收器，该回收器是针对老年代垃圾回收的，通过参数-XX:+UseConcMarkSweepGC进行设置。</p>
<p>CMS垃圾回收器的执行过程如下：</p>
<p> <img src="https://threadv.github.io/assets2/2184951-cd90513432053c9a.png" alt="img"></p>
<ul>
<li>初始化标记(CMS-initial-mark) ,标记root，会导致stw； </li>
<li>并发标记(CMS-concurrent-mark)，与用户线程同时运行； </li>
<li>预清理（CMS-concurrent-preclean），与用户线程同时运行； </li>
<li>重新标记(CMS-remark) ，会导致stw； </li>
<li>并发清除(CMS-concurrent-sweep)，与用户线程同时运行； </li>
<li>调整堆大小，设置CMS在清理之后进行内存压缩，目的是清理内存中的碎片；</li>
<li>并发重置状态等待下次CMS的触发(CMS-concurrent-reset)，与用户线程同时运行； </li>
</ul>
<h4 id="3-3-1、测试"><a href="#3-3-1、测试" class="headerlink" title="3.3.1、测试"></a>3.3.1、测试</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#</span>设置启动参数</span><br><span class="line">-XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xms16m -Xmx16m</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>运行日志</span><br><span class="line">[GC (Allocation Failure) [ParNew: 4926K-&gt;512K(4928K), 0.0041843 secs] 9424K-&gt;6736K(15872K), 0.0042168 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>第一步，初始标记</span><br><span class="line">[GC (CMS Initial Mark) [1 CMS-initial-mark: 6224K(10944K)] 6824K(15872K), 0.0004209 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"><span class="meta">#</span>第二步，并发标记</span><br><span class="line">[CMS-concurrent-mark-start]</span><br><span class="line">[CMS-concurrent-mark: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"><span class="meta">#</span>第三步，预处理</span><br><span class="line">[CMS-concurrent-preclean-start]</span><br><span class="line">[CMS-concurrent-preclean: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"><span class="meta">#</span>第四步，重新标记</span><br><span class="line">[GC (CMS Final Remark) [YG occupancy: 1657 K (4928 K)][Rescan (parallel) , 0.0005811 secs][weak refs processing, 0.0000136 secs][class unloading, 0.0003671 secs][scrub symbol table, 0.0006813 secs][scrub string table, 0.0001216 secs][1 CMS-remark: 6224K(10944K)] 7881K(15872K), 0.0018324 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"><span class="meta">#</span>第五步，并发清理</span><br><span class="line">[CMS-concurrent-sweep-start]</span><br><span class="line">[CMS-concurrent-sweep: 0.004/0.004 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line"><span class="meta">#</span>第六步，重置</span><br><span class="line">[CMS-concurrent-reset-start]</span><br><span class="line">[CMS-concurrent-reset: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]</span><br></pre></td></tr></table></figure>
<p>由以上日志信息，可以看出CMS执行的过程。</p>
<h3 id="3-4、G1垃圾收集器（重点）"><a href="#3-4、G1垃圾收集器（重点）" class="headerlink" title="3.4、G1垃圾收集器（重点）"></a>3.4、G1垃圾收集器（重点）</h3><p>G1垃圾收集器是在jdk1.7中正式使用的全新的垃圾收集器，oracle官方计划在jdk9中将G1变成默认的垃圾收集器，以替代CMS。</p>
<p>G1的设计原则就是简化JVM性能调优，开发人员只需要简单的三步即可完成调优：</p>
<ol>
<li>第一步，开启G1垃圾收集器</li>
<li>第二步，设置堆的最大内存</li>
<li>第三步，设置最大的停顿时间</li>
</ol>
<p>G1中提供了三种模式垃圾回收模式，Young GC、Mixed GC 和 Full GC，在不同的条件下被触发。</p>
<h4 id="3-4-1、原理"><a href="#3-4-1、原理" class="headerlink" title="3.4.1、原理"></a>3.4.1、原理</h4><p>G1垃圾收集器相对比其他收集器而言，最大的区别在于它取消了年轻代、老年代的物理划分，取而代之的是将堆划分为若干个区域（Region），这些区域中包含了有逻辑上的年轻代、老年代区域。</p>
<p>这样做的好处就是，我们再也不用单独的空间对每个代进行设置了，不用担心每个代内存是否足够。</p>
<p> <img src="https://threadv.github.io/assets2/20161222153407_691.png" alt="img"></p>
<p> <img src="https://threadv.github.io/assets2/20161222153407_471.png" alt="img"></p>
<p>在G1划分的区域中，年轻代的垃圾收集依然采用暂停所有应用线程的方式，将存活对象拷贝到老年代或者Survivor空间，G1收集器通过将对象从一个区域复制到另外一个区域，完成了清理工作。</p>
<p>这就意味着，在正常的处理过程中，G1完成了堆的压缩（至少是部分堆的压缩），这样也就不会有cms内存碎片问题的存在了。</p>
<p>在G1中，有一种特殊的区域，叫Humongous区域。 </p>
<ul>
<li>如果一个对象占用的空间超过了分区容量50%以上，G1收集器就认为这是一个巨型对象。</li>
<li>这些巨型对象，默认直接会被分配在老年代，但是如果它是一个短期存在的巨型对象，就会对垃圾收集器造成负面影响。</li>
<li>为了解决这个问题，G1划分了一个Humongous区，它用来专门存放巨型对象。如果一个H区装不下一个巨型对象，那么G1会寻找连续的H分区来存储。为了能找到连续的H区，有时候不得不启动Full GC。</li>
</ul>
<h4 id="3-4-2、Young-GC"><a href="#3-4-2、Young-GC" class="headerlink" title="3.4.2、Young GC"></a>3.4.2、Young GC</h4><p>Young GC主要是对Eden区进行GC，它在Eden空间耗尽时会被触发。</p>
<ul>
<li>Eden空间的数据移动到Survivor空间中，如果Survivor空间不够，Eden空间的部分数据会直接晋升到年老代空间。</li>
<li>Survivor区的数据移动到新的Survivor区中，也有部分数据晋升到老年代空间中。</li>
<li><p>最终Eden空间的数据为空，GC停止工作，应用线程继续执行。</p>
<p><img src="https://threadv.github.io/assets2/20161222153407_47.png" alt="img"></p>
<p><img src="https://threadv.github.io/assets2/20161222153408_747.png" alt="img"></p>
</li>
</ul>
<h5 id="3-4-2-1、Remembered-Set（已记忆集合）"><a href="#3-4-2-1、Remembered-Set（已记忆集合）" class="headerlink" title="3.4.2.1、Remembered Set（已记忆集合）"></a>3.4.2.1、Remembered Set（已记忆集合）</h5><p>在GC年轻代的对象时，我们如何找到年轻代中对象的根对象呢？ </p>
<p>根对象可能是在年轻代中，也可以在老年代中，那么老年代中的所有对象都是根么？</p>
<p>如果全量扫描老年代，那么这样扫描下来会耗费大量的时间。</p>
<p>于是，G1引进了RSet的概念。它的全称是Remembered Set，其作用是跟踪指向某个堆内的对象引用。</p>
<p> <img src="https://threadv.github.io/assets2/2184951-bd04a968d1c8c895.png" alt="img"></p>
<p>每个Region初始化时，会初始化一个RSet，该集合用来记录并跟踪其它Region指向该Region中对象的引用，每个Region默认按照512Kb划分成多个Card，所以RSet需要记录的东西应该是 xx Region的 xx Card。</p>
<h4 id="3-4-3、Mixed-GC"><a href="#3-4-3、Mixed-GC" class="headerlink" title="3.4.3、Mixed GC"></a>3.4.3、Mixed GC</h4><p>当越来越多的对象晋升到老年代old region时，为了避免堆内存被耗尽，虚拟机会触发一个混合的垃圾收集器，即Mixed GC，该算法并不是一个Old GC，除了回收整个Young Region，还会回收一部分的Old Region，这里需要注意：是一部分老年代，而不是全部老年代，可以选择哪些old region进行收集，从而可以对垃圾回收的耗时时间进行控制。也要注意的是Mixed GC 并不是 Full GC。</p>
<p>MixedGC什么时候触发？  由参数 -XX:InitiatingHeapOccupancyPercent=n 决定。默认：45%，该参数的意思是：当老年代大小占整个堆大小百分比达到该阀值时触发。</p>
<p>它的GC步骤分2步：</p>
<ol>
<li>全局并发标记（global concurrent marking）</li>
<li>拷贝存活对象（evacuation）</li>
</ol>
<h5 id="3-4-3-1、全局并发标记"><a href="#3-4-3-1、全局并发标记" class="headerlink" title="3.4.3.1、全局并发标记"></a>3.4.3.1、全局并发标记</h5><p>全局并发标记，执行过程分为五个步骤：</p>
<ul>
<li>初始标记（initial mark，STW）<ul>
<li>标记从根节点直接可达的对象，这个阶段会执行一次年轻代GC，会产生全局停顿。</li>
</ul>
</li>
<li>根区域扫描（root region scan）<ul>
<li>G1 GC 在初始标记的存活区扫描对老年代的引用，并标记被引用的对象。</li>
<li>该阶段与应用程序（非 STW）同时运行，并且只有完成该阶段后，才能开始下一次 STW 年轻代垃圾回收。</li>
</ul>
</li>
<li>并发标记（Concurrent Marking）<ul>
<li>G1 GC 在整个堆中查找可访问的（存活的）对象。该阶段与应用程序同时运行，可以被 STW 年轻代垃圾回收中断。</li>
</ul>
</li>
<li>重新标记（Remark，STW）<ul>
<li>该阶段是 STW 回收，因为程序在运行，针对上一次的标记进行修正。</li>
</ul>
</li>
<li>清除垃圾（Cleanup，STW）<ul>
<li>清点和重置标记状态，该阶段会STW，这个阶段并不会实际上去做垃圾的收集，等待evacuation阶段来回收。</li>
</ul>
</li>
</ul>
<h5 id="3-4-3-2、拷贝存活对象"><a href="#3-4-3-2、拷贝存活对象" class="headerlink" title="3.4.3.2、拷贝存活对象"></a>3.4.3.2、拷贝存活对象</h5><p>Evacuation阶段是全暂停的。该阶段把一部分Region里的活对象拷贝到另一部分Region中，从而实现垃圾的回收清理。</p>
<h4 id="3-4-4、G1收集器相关参数"><a href="#3-4-4、G1收集器相关参数" class="headerlink" title="3.4.4、G1收集器相关参数"></a>3.4.4、G1收集器相关参数</h4><ul>
<li>-XX:+UseG1GC<ul>
<li>使用 G1 垃圾收集器</li>
</ul>
</li>
<li>-XX:MaxGCPauseMillis<ul>
<li>设置期望达到的最大GC停顿时间指标（JVM会尽力实现，但不保证达到），默认值是 200 毫秒。</li>
</ul>
</li>
<li>-XX:G1HeapRegionSize=n<ul>
<li>设置的 G1 区域的大小。值是 2 的幂，范围是 1 MB 到 32 MB 之间。目标是根据最小的 Java 堆大小划分出约 2048 个区域。</li>
<li>默认是堆内存的1/2000。</li>
</ul>
</li>
<li>-XX:ParallelGCThreads=n<ul>
<li>设置 STW 工作线程数的值。将 n 的值设置为逻辑处理器的数量。n 的值与逻辑处理器的数量相同，最多为 8。</li>
</ul>
</li>
<li>-XX:ConcGCThreads=n<ul>
<li>设置并行标记的线程数。将 n 设置为并行垃圾回收线程数 (ParallelGCThreads) 的 1/4 左右。</li>
</ul>
</li>
<li>-XX:InitiatingHeapOccupancyPercent=n<ul>
<li>设置触发标记周期的 Java 堆占用率阈值。默认占用率是整个 Java 堆的 45%。</li>
</ul>
</li>
</ul>
<h4 id="3-4-5、测试"><a href="#3-4-5、测试" class="headerlink" title="3.4.5、测试"></a>3.4.5、测试</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -XX:+PrintGCDetails -Xmx256m</span><br><span class="line"></span><br><span class="line"><span class="meta">#</span>日志</span><br><span class="line">[GC pause (G1 Evacuation Pause) (young), 0.0044882 secs]</span><br><span class="line">   [Parallel Time: 3.7 ms, GC Workers: 3]</span><br><span class="line">      [GC Worker Start (ms): Min: 14763.7, Avg: 14763.8, Max: 14763.8, Diff: 0.1]</span><br><span class="line">      #扫描根节点</span><br><span class="line">      [Ext Root Scanning (ms): Min: 0.2, Avg: 0.3, Max: 0.3, Diff: 0.1, Sum: 0.8]</span><br><span class="line">      #更新RS区域所消耗的时间</span><br><span class="line">      [Update RS (ms): Min: 1.8, Avg: 1.9, Max: 1.9, Diff: 0.2, Sum: 5.6]</span><br><span class="line">         [Processed Buffers: Min: 1, Avg: 1.7, Max: 3, Diff: 2, Sum: 5]</span><br><span class="line">      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]</span><br><span class="line">      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]</span><br><span class="line">      #对象拷贝</span><br><span class="line">      [Object Copy (ms): Min: 1.1, Avg: 1.2, Max: 1.3, Diff: 0.2, Sum: 3.6]</span><br><span class="line">      [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 0.2]</span><br><span class="line">         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 3]</span><br><span class="line">      [GC Worker Other (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]</span><br><span class="line">      [GC Worker Total (ms): Min: 3.4, Avg: 3.4, Max: 3.5, Diff: 0.1, Sum: 10.3]</span><br><span class="line">      [GC Worker End (ms): Min: 14767.2, Avg: 14767.2, Max: 14767.3, Diff: 0.1]</span><br><span class="line">   [Code Root Fixup: 0.0 ms]</span><br><span class="line">   [Code Root Purge: 0.0 ms]</span><br><span class="line">   [Clear CT: 0.0 ms] #清空CardTable</span><br><span class="line">   [Other: 0.7 ms]</span><br><span class="line">      [Choose CSet: 0.0 ms] #选取CSet</span><br><span class="line">      [Ref Proc: 0.5 ms] #弱引用、软引用的处理耗时</span><br><span class="line">      [Ref Enq: 0.0 ms] #弱引用、软引用的入队耗时</span><br><span class="line">      [Redirty Cards: 0.0 ms]</span><br><span class="line">      [Humongous Register: 0.0 ms] #大对象区域注册耗时</span><br><span class="line">      [Humongous Reclaim: 0.0 ms] #大对象区域回收耗时</span><br><span class="line">      [Free CSet: 0.0 ms]</span><br><span class="line">   [Eden: 7168.0K(7168.0K)-&gt;0.0B(13.0M) Survivors: 2048.0K-&gt;2048.0K Heap: 55.5M(192.0M)-&gt;48.5M(192.0M)] #年轻代的大小统计</span><br><span class="line"> [Times: user=0.00 sys=0.00, real=0.00 secs]</span><br></pre></td></tr></table></figure>
<h4 id="3-4-6、对于G1垃圾收集器优化建议"><a href="#3-4-6、对于G1垃圾收集器优化建议" class="headerlink" title="3.4.6、对于G1垃圾收集器优化建议"></a>3.4.6、对于G1垃圾收集器优化建议</h4><ul>
<li>年轻代大小<ul>
<li>避免使用 -Xmn 选项或 -XX:NewRatio 等其他相关选项显式设置年轻代大小。</li>
<li>固定年轻代的大小会覆盖暂停时间目标。</li>
</ul>
</li>
<li>暂停时间目标不要太过严苛<ul>
<li>G1 GC 的吞吐量目标是 90% 的应用程序时间和 10%的垃圾回收时间。</li>
<li>评估 G1 GC 的吞吐量时，暂停时间目标不要太严苛。目标太过严苛表示您愿意承受更多的垃圾回收开销，而这会直接影响到吞吐量。</li>
</ul>
</li>
</ul>
<h2 id="4、可视化GC日志分析工具"><a href="#4、可视化GC日志分析工具" class="headerlink" title="4、可视化GC日志分析工具"></a>4、可视化GC日志分析工具</h2><h3 id="4-1、GC日志输出参数"><a href="#4-1、GC日志输出参数" class="headerlink" title="4.1、GC日志输出参数"></a>4.1、GC日志输出参数</h3><p>前面通过-XX:+PrintGCDetails可以对GC日志进行打印，我们就可以在控制台查看，这样虽然可以查看GC的信息，但是并不直观，可以借助于第三方的GC日志分析工具进行查看。</p>
<p>在日志打印输出涉及到的参数如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">-XX:+PrintGC 输出GC日志</span><br><span class="line">-XX:+PrintGCDetails 输出GC的详细日志</span><br><span class="line">-XX:+PrintGCTimeStamps 输出GC的时间戳（以基准时间的形式）</span><br><span class="line">-XX:+PrintGCDateStamps 输出GC的时间戳（以日期的形式，如 2013-05-04T21:53:59.234+0800）</span><br><span class="line">-XX:+PrintHeapAtGC 在进行GC的前后打印出堆的信息</span><br><span class="line">-Xloggc:../logs/gc.log 日志文件的输出路径</span><br></pre></td></tr></table></figure>
<p>测试：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xmx256m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:F://test//gc.log</span><br></pre></td></tr></table></figure>
<p>运行后就可以在E盘下生成gc.log文件。</p>
<p>如下：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">Java HotSpot(TM) 64-Bit Server VM (25.144-b01) for windows-amd64 JRE (1.8.0_144-b01), built on Jul 21 2017 21:57:33 by "java_re" with MS VC++ 10.0 (VS2010)</span><br><span class="line">Memory: 4k page, physical 12582392k(1939600k free), swap 17300984k(5567740k free)</span><br><span class="line">CommandLine flags: -XX:InitialHeapSize=201318272 -XX:MaxGCPauseMillis=100 -XX:MaxHeapSize=268435456 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC -XX:-UseLargePagesIndividualAllocation </span><br><span class="line">&#123;Heap before GC invocations=0 (full 0):</span><br><span class="line"> garbage-first heap   total 196608K, used 9216K [0x00000000f0000000, 0x00000000f0100600, 0x0000000100000000)</span><br><span class="line">  region size 1024K, 9 young (9216K), 0 survivors (0K)</span><br><span class="line"> Metaspace       used 3491K, capacity 4500K, committed 4864K, reserved 1056768K</span><br><span class="line">  class space    used 381K, capacity 388K, committed 512K, reserved 1048576K</span><br><span class="line">2018-09-24T23:06:02.230+0800: 0.379: [GC pause (G1 Evacuation Pause) (young), 0.0031038 secs]</span><br><span class="line">   [Parallel Time: 2.8 ms, GC Workers: 3]</span><br><span class="line">      [GC Worker Start (ms): Min: 378.6, Avg: 378.8, Max: 379.0, Diff: 0.3]</span><br><span class="line">      [Ext Root Scanning (ms): Min: 0.0, Avg: 0.4, Max: 0.8, Diff: 0.8, Sum: 1.3]</span><br><span class="line">      [Update RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]</span><br><span class="line">         [Processed Buffers: Min: 0, Avg: 0.0, Max: 0, Diff: 0, Sum: 0]</span><br><span class="line">      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]</span><br><span class="line">      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.1]</span><br><span class="line">      [Object Copy (ms): Min: 1.8, Avg: 1.9, Max: 1.9, Diff: 0.1, Sum: 5.6]</span><br><span class="line">      [Termination (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]</span><br><span class="line">         [Termination Attempts: Min: 1, Avg: 1.0, Max: 1, Diff: 0, Sum: 3]</span><br><span class="line">      [GC Worker Other (ms): Min: 0.0, Avg: 0.2, Max: 0.6, Diff: 0.6, Sum: 0.6]</span><br><span class="line">      [GC Worker Total (ms): Min: 2.4, Avg: 2.5, Max: 2.7, Diff: 0.3, Sum: 7.6]</span><br><span class="line">      [GC Worker End (ms): Min: 381.4, Avg: 381.4, Max: 381.4, Diff: 0.0]</span><br><span class="line">   [Code Root Fixup: 0.0 ms]</span><br><span class="line">   [Code Root Purge: 0.0 ms]</span><br><span class="line">   [Clear CT: 0.0 ms]</span><br><span class="line">   [Other: 0.2 ms]</span><br><span class="line">      [Choose CSet: 0.0 ms]</span><br><span class="line">      [Ref Proc: 0.1 ms]</span><br><span class="line">      [Ref Enq: 0.0 ms]</span><br><span class="line">      [Redirty Cards: 0.0 ms]</span><br><span class="line">      [Humongous Register: 0.0 ms]</span><br><span class="line">      [Humongous Reclaim: 0.0 ms]</span><br><span class="line">      [Free CSet: 0.0 ms]</span><br><span class="line">   [Eden: 9216.0K(9216.0K)-&gt;0.0B(7168.0K) Survivors: 0.0B-&gt;2048.0K Heap: 9216.0K(192.0M)-&gt;1888.0K(192.0M)]</span><br><span class="line">Heap after GC invocations=1 (full 0):</span><br><span class="line"> garbage-first heap   total 196608K, used 1888K [0x00000000f0000000, 0x00000000f0100600, 0x0000000100000000)</span><br><span class="line">  region size 1024K, 2 young (2048K), 2 survivors (2048K)</span><br><span class="line"> Metaspace       used 3491K, capacity 4500K, committed 4864K, reserved 1056768K</span><br><span class="line">  class space    used 381K, capacity 388K, committed 512K, reserved 1048576K</span><br><span class="line">&#125;</span><br><span class="line"> [Times: user=0.00 sys=0.00, real=0.00 secs] </span><br><span class="line">&#123;Heap before GC invocations=1 (full 0):</span><br><span class="line"> garbage-first heap   total 196608K, used 9056K [0x00000000f0000000, 0x00000000f0100600, 0x0000000100000000)</span><br><span class="line">  region size 1024K, 9 young (9216K), 2 survivors (2048K)</span><br><span class="line"> Metaspace       used 3492K, capacity 4500K, committed 4864K, reserved 1056768K</span><br><span class="line">  class space    used 381K, capacity 388K, committed 512K, reserved 1048576K</span><br><span class="line">2018-09-24T23:06:02.310+0800: 0.458: [GC pause (G1 Evacuation Pause) (young), 0.0070126 secs]</span><br><span class="line">。。。。。。。。。。。。。。。。。。。</span><br></pre></td></tr></table></figure>
<h3 id="4-2、GC-Easy-可视化工具"><a href="#4-2、GC-Easy-可视化工具" class="headerlink" title="4.2、GC Easy 可视化工具"></a>4.2、GC Easy 可视化工具</h3><p>GC Easy是一款在线的可视化工具，易用、功能强大，网站：</p>
<p><a href="http://gceasy.io/" target="_blank" rel="noopener">http://gceasy.io/</a></p>
<p> <img src="https://threadv.github.io/assets2/1537803536253.png" alt="1537803536253"></p>
<p>上传后，点击“Analyze”按钮，即可查看报告。</p>
<p> <img src="https://threadv.github.io/assets2/1537804265054.png" alt="1537804265054"></p>
<p> <img src="https://threadv.github.io/assets2/1537804287484.png" alt="1537804287484"></p>
<p> <img src="https://threadv.github.io/assets2/1537804311560.png" alt="1537804311560"></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/28/Jvm-GC/" data-id="ckcc5iwit000gq4uw2h2ke5on" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/jvm/">jvm</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-test_build_sh" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/26/test_build_sh/" class="article-date">
  <time datetime="2018-12-26T03:37:26.000Z" itemprop="datePublished">2018-12-26</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/26/test_build_sh/">test.build</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h5 id="test-build"><a href="#test-build" class="headerlink" title="test.build"></a>test.build</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">svn up /data/storybookapi2_src</span><br><span class="line">cd /data/storybookapi2_src</span><br><span class="line">#mvn tomcat7:deploy -e</span><br><span class="line">mvn clean</span><br><span class="line">mvn package -Dmaven.test.skip=true</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/26/test_build_sh/" data-id="ckcc5iwll003iq4uwdwsnzltn" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/docker/">docker</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-test_run" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/26/test_run/" class="article-date">
  <time datetime="2018-12-26T03:37:26.000Z" itemprop="datePublished">2018-12-26</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/26/test_run/">test_run</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h5 id="test-run"><a href="#test-run" class="headerlink" title="test_run"></a>test_run</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line">#svn up /data/storybookapi_src</span><br><span class="line">#cd /data/storybookapi_src</span><br><span class="line">#mvn tomcat7:deploy -e</span><br><span class="line">#mvn clean</span><br><span class="line">#mvn package</span><br><span class="line">ps -ef | grep storybookapi2 | grep -v grep | cut -c 9-15 | xargs kill -s 9 </span><br><span class="line">java -Xmx256m -jar /data/storybookapi2_src/target/storybookapi-1.0-SNAPSHOT.jar -Xmx256m --spring.profiles.active=test &amp;</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/26/test_run/" data-id="ckcc5iwlm003lq4uw6bol8ae1" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/docker/">docker</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-Dockerfile" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/2018/12/24/Dockerfile/" class="article-date">
  <time datetime="2018-12-24T07:01:26.000Z" itemprop="datePublished">2018-12-24</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/2018/12/24/Dockerfile/">Dockerfile</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h5 id="Dockerfile"><a href="#Dockerfile" class="headerlink" title="Dockerfile"></a>Dockerfile</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"># version 0.0.1-snapshot</span><br><span class="line"># 从一个基础镜像centos:6.8开始构建</span><br><span class="line">#FROM centos:6.8</span><br><span class="line">FROM java:openjdk-8u111-jdk</span><br><span class="line"># 维护者信息</span><br><span class="line">MAINTAINER storybook &quot;weisiliang@ifenghui.com&quot;</span><br><span class="line"># 将Dockerfile上下文中的nginx.repo复制到容器中的yum源位置</span><br><span class="line">#COPY ./nginx.repo /etc/yum.repos.d/nginx.repo</span><br><span class="line">#RUN yum makecache</span><br><span class="line">ENV TIME_ZONE Asia/Shanghai</span><br><span class="line"></span><br><span class="line">RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \</span><br><span class="line">&amp;&amp; echo &quot;$&#123;TIME_ZONE&#125;&quot; &gt; /etc/timezone </span><br><span class="line"></span><br><span class="line">#安装java8</span><br><span class="line">#RUN yum install -y java-1.8.0-openjdk</span><br><span class="line"></span><br><span class="line">#安装svn</span><br><span class="line">#RUN yum install -y svn</span><br><span class="line"></span><br><span class="line">#安装maven</span><br><span class="line">#RUN yum install -y maven</span><br><span class="line"></span><br><span class="line">#RUN yum -y install fontconfig</span><br><span class="line">ADD simhei.ttf /usr/share/fonts/hei/simhei.ttf</span><br><span class="line">WORKDIR /usr/share/fonts/hei</span><br><span class="line">#RUN mkfontscale </span><br><span class="line">RUN fc-cache -fv</span><br><span class="line">#RUN source /etc/profile</span><br><span class="line"></span><br><span class="line">#创建目录：/opt/storybookfenxiao</span><br><span class="line"></span><br><span class="line">#复制 jar到目录下</span><br><span class="line">RUN mkdir -p /opt/storybookfenxiao</span><br><span class="line">RUN mkdir -p /data/fenxiao1808</span><br><span class="line">ADD fenxiao.jpg /data/fenxiao1808/fenxiao.jpg</span><br><span class="line">ADD fenxiao2.jpg /data/fenxiao1808/fenxiao2.jpg</span><br><span class="line">ADD fenxiao3.jpg /data/fenxiao1808/fenxiao3.jpg</span><br><span class="line">ADD fenxiao5.jpg /data/fenxiao1808/fenxiao5.jpg</span><br><span class="line">RUN chmod -R 777 /data</span><br><span class="line"></span><br><span class="line">#复制正式和测试运行脚本到目录中</span><br><span class="line">ADD start-product.sh /opt/storybookfenxiao/start-product.sh</span><br><span class="line">#完成</span><br><span class="line">ADD start-test.sh /opt/storybookfenxiao/start-test.sh</span><br><span class="line">#完成</span><br><span class="line">ADD start-beta.sh /opt/storybookfenxiao/start-beta.sh</span><br><span class="line">#添加证书</span><br><span class="line">ADD apiclient_cert.p12 /data/apiclient_cert/apiclient_cert.p12</span><br><span class="line"></span><br><span class="line">#copy项目</span><br><span class="line">COPY fenxiao.jar /opt/storybookfenxiao/fenxiao.jar</span><br><span class="line"></span><br><span class="line">#创建镜像</span><br><span class="line"></span><br><span class="line"># 安装wget</span><br><span class="line">#RUN yum install -y wget</span><br><span class="line"># 安装aliyun yum 源头 </span><br><span class="line">#RUN wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo</span><br><span class="line">#RUN yum clean all</span><br><span class="line">#RUN yum makecache</span><br><span class="line"># 安装nginx</span><br><span class="line">#RUN yum install -y nginx</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"># 修改nginx首页信息</span><br><span class="line">#RUN echo &quot;home page of container niginx server&quot; &gt; /usr/share/nginx/html/index.html</span><br><span class="line"># 暴露80端口</span><br><span class="line">EXPOSE 8080</span><br><span class="line">#运行</span><br><span class="line">#RUN nginx</span><br><span class="line">#CMD docker run -t -i -p 80:80 nginx/nginx-1</span><br><span class="line">#sudo docker run -it -p 80:80  -v `pwd`/logs:/var/log/nginx dockerfile/nginx</span><br><span class="line">#CMD docker run -t -i storybook/java8</span><br><span class="line">#CMD [&quot;java&quot;, &quot;-jar&quot;, &quot;/usr/local/storybookapi-1.0-SNAPSHOT.jar&quot;]</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/2018/12/24/Dockerfile/" data-id="ckcc5iwic0004q4uwcy8iuf95" class="article-share-link">Teilen</a>
      
      
  <ul class="article-tag-list"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/docker/">docker</a></li></ul>

    </footer>
  </div>
  
</article>


  


  <nav id="page-nav">
    
    <a class="extend prev" rel="prev" href="/page/3/">&laquo; zurück</a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/page/5/">5</a><a class="page-number" href="/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/page/15/">15</a><a class="extend next" rel="next" href="/page/5/">weiter &raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tags</h3>
    <div class="widget">
      <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/tags/Design-Patterns/">Design Patterns</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Git/">Git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Html/">Html</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Http/">Http</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/JavaScript/">JavaScript</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/Sort/">Sort</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/algorithm/">algorithm</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/ali-weixin-pay/">ali/weixin pay</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/docker/">docker</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/elasticsearch/">elasticsearch</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/go/">go</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/hexo/">hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/idea/">idea</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java/">java</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/jvm/">jvm</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/linux/">linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/logstash/">logstash</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mysql/">mysql</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/php/">php</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/pytest/">pytest</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/python/">python</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/springboot/">springboot</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/util/">util</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vue/">vue</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/wechat/">wechat</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/我的世界/">我的世界</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/消息队列/">消息队列</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/线程/">线程</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Tag Cloud</h3>
    <div class="widget tagcloud">
      <a href="/tags/Design-Patterns/" style="font-size: 16.36px;">Design Patterns</a> <a href="/tags/Git/" style="font-size: 10px;">Git</a> <a href="/tags/Html/" style="font-size: 10px;">Html</a> <a href="/tags/Http/" style="font-size: 12.73px;">Http</a> <a href="/tags/JavaScript/" style="font-size: 15.45px;">JavaScript</a> <a href="/tags/Sort/" style="font-size: 18.18px;">Sort</a> <a href="/tags/algorithm/" style="font-size: 11.82px;">algorithm</a> <a href="/tags/ali-weixin-pay/" style="font-size: 13.64px;">ali/weixin pay</a> <a href="/tags/docker/" style="font-size: 17.27px;">docker</a> <a href="/tags/elasticsearch/" style="font-size: 10px;">elasticsearch</a> <a href="/tags/go/" style="font-size: 11.82px;">go</a> <a href="/tags/hexo/" style="font-size: 10px;">hexo</a> <a href="/tags/idea/" style="font-size: 10px;">idea</a> <a href="/tags/java/" style="font-size: 20px;">java</a> <a href="/tags/jvm/" style="font-size: 11.82px;">jvm</a> <a href="/tags/linux/" style="font-size: 18.18px;">linux</a> <a href="/tags/logstash/" style="font-size: 12.73px;">logstash</a> <a href="/tags/mysql/" style="font-size: 14.55px;">mysql</a> <a href="/tags/php/" style="font-size: 11.82px;">php</a> <a href="/tags/pytest/" style="font-size: 10px;">pytest</a> <a href="/tags/python/" style="font-size: 13.64px;">python</a> <a href="/tags/springboot/" style="font-size: 17.27px;">springboot</a> <a href="/tags/util/" style="font-size: 19.09px;">util</a> <a href="/tags/vue/" style="font-size: 10px;">vue</a> <a href="/tags/wechat/" style="font-size: 10.91px;">wechat</a> <a href="/tags/我的世界/" style="font-size: 10px;">我的世界</a> <a href="/tags/消息队列/" style="font-size: 10.91px;">消息队列</a> <a href="/tags/线程/" style="font-size: 11.82px;">线程</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">Archiv</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/05/">May 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/04/">April 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/03/">March 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/01/">January 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/10/">October 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/08/">August 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">June 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/04/">April 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/03/">March 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/02/">February 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/01/">January 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/12/">December 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/11/">November 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/10/">October 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/09/">September 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/07/">July 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/06/">June 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/05/">May 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/04/">April 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">March 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/02/">February 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/01/">January 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2017/12/">December 2017</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">letzter Beitrag</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2020/05/17/linux/linux_shell/">linux—shell</a>
          </li>
        
          <li>
            <a href="/2020/05/16/linux/linux_awk_sed/">linux-awk\sed 示例</a>
          </li>
        
          <li>
            <a href="/2020/04/11/linux/linux_bash/">linux—bash</a>
          </li>
        
          <li>
            <a href="/2020/03/29/hello-world/">Hello World</a>
          </li>
        
          <li>
            <a href="/2020/03/16/go基础/">go基础知识</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2020 vchen<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/script.js"></script>



  </div>
</body>
</html>